#!/bin/sh

# Copyright (c) 2021-2024 刘富频
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


# last line mode :set foldmethod=marker
# command mode zM  fold close all
# command mode zR  fold open all

# {{{ coding convention

# 1. The variable/function name starts with underscore "_" means that it is a private variable/function.
# 2. 0 represents the boolean value false
# 3. 1 represents the boolean value true

# }}}
##############################################################################
# {{{ utils

COLOR_RED='\033[0;31m'          # Red
COLOR_GREEN='\033[0;32m'        # Green
COLOR_YELLOW='\033[0;33m'       # Yellow
COLOR_BLUE='\033[0;94m'         # Blue
COLOR_PURPLE='\033[0;35m'       # Purple
COLOR_OFF='\033[0m'             # Reset

print() {
    printf '%b' "$*"
}

echo() {
    printf '%b\n' "$*"
}

note() {
    printf '%b\n' "${COLOR_YELLOW}🔔  $*${COLOR_OFF}" >&2
}

warn() {
    printf '%b\n' "${COLOR_YELLOW}⚠️  $*${COLOR_OFF}" >&2
}

success() {
    printf '%b\n' "${COLOR_GREEN}✅️  $*${COLOR_OFF}" >&2
}

error() {
    printf '%b\n' "${COLOR_RED}💔  ndk-pkg: $*${COLOR_OFF}" >&2
}

abort() {
    EXIT_STATUS_CODE="$1"
    shift
    printf '%b\n' "${COLOR_RED}💔  ndk-pkg: $*${COLOR_OFF}" >&2
    exit "$EXIT_STATUS_CODE"
}

step() {
    STEP_NUM=$(expr ${STEP_NUM-0} + 1)
    STEP_MESSAGE="$*"
    printf '\n%b\n' "${COLOR_PURPLE}=>> STEP ${STEP_NUM} : ${STEP_MESSAGE} ${COLOR_OFF}"
}

run() {
    echo "${COLOR_PURPLE}==>${COLOR_OFF} ${COLOR_GREEN}$@${COLOR_OFF}"
    eval "$@"
}

list_size() {
    printf '%s\n' "$#"
}

isInteger() {
    case "${1#[+-]}" in
        (*[!0123456789]*) return 1 ;;
        ('')              return 1 ;;
        (*)               return 0 ;;
    esac
}

bppend_to_PATH() {
    case ":${PATH}:" in
        *:"$1":*) ;;
        *) export PATH="$1:$PATH" ;;
    esac
}

bppend_to_ACLOCAL_PATH() {
    case ":${ACLOCAL_PATH}:" in
        *:"$1":*) ;;
        *) export ACLOCAL_PATH="$1:$ACLOCAL_PATH" ;;
    esac
}

sedInPlace() {
    if [ "${DUMP_SED:-0}" = 1 ] ; then
        if [ -z "$SED" ] ; then
            SED="$(command -v gsed || command -v sed)" || abort 1 "command not found: gsed"
        fi

        export SED

        "$NDKPKG_CORE_DIR/sed-in-place" "$@"
    else
        sed -i "$@"
    fi
}

git() {
    if [ -z "$SSL_CERT_FILE" ] ; then
        command git "$@"
    else
        command git -c http.sslCAInfo="$SSL_CERT_FILE" "$@"
    fi
}

# git_checkout <URL> --ref-from=<FROM> --ref-to=<TO> --depth=<N> -B <CHECKOUT-BRANCH-NAME> -C <WORKDIR> --recursive
git_checkout() {
    OLDCWD="$PWD"

    unset GIT_FETCH_FROM_URL
    unset GIT_FETCH_FROM_REF
    unset GIT_FETCH_TO___REF
    unset GIT_FETCH_DEPTH
    unset GIT_FETCH_SUBMODULE_RECURSIVE
    unset GIT_CHECKOUT_BRANCH_NAME
    unset GIT_WORK_DIR

    if [ -z "$NDKPKG_URL_TRANSFORM" ] ; then
        GIT_FETCH_FROM_URL="$1"
    else
        GIT_FETCH_FROM_URL="$("$NDKPKG_URL_TRANSFORM" "$1")"
    fi

    shift

    while [ -n "$1" ]
    do
        case $1 in
            --ref-from=*)
                GIT_FETCH_FROM_REF="${1#*=}"
                ;;
            --ref-to=*)
                GIT_FETCH_TO___REF="${1#*=}"
                ;;
            --depth=*)
                GIT_FETCH_DEPTH="${1#*=}"
                ;;
            -B) shift
                GIT_CHECKOUT_BRANCH_NAME="${1#*=}"
                ;;
            -C) shift
                GIT_WORK_DIR="$1"
                ;;
            --recursive)
                GIT_FETCH_SUBMODULE_RECURSIVE=1
                ;;
        esac
        shift
    done

    [ -z "$GIT_FETCH_DEPTH" ] && GIT_FETCH_DEPTH=1
    [ -z "$GIT_FETCH_FROM_REF" ] && GIT_FETCH_FROM_REF='HEAD'
    [ -z "$GIT_FETCH_TO___REF" ] && GIT_FETCH_TO___REF='refs/remotes/origin/master'

    [ -z "$GIT_CHECKOUT_BRANCH_NAME" ] && GIT_CHECKOUT_BRANCH_NAME="${GIT_FETCH_TO___REF##*/}"

    if [    -n "$GIT_WORK_DIR" ] ; then
        [   -d "$GIT_WORK_DIR" ] || run install -d "$GIT_WORK_DIR"
        run cd "$GIT_WORK_DIR"
    fi

    run git -c init.defaultBranch=master init
    run git remote add origin "$GIT_FETCH_FROM_URL"
    run git -c protocol.version=2 fetch --progress --depth="$GIT_FETCH_DEPTH" origin "$GIT_FETCH_FROM_REF:$GIT_FETCH_TO___REF"
    run git checkout --progress --force -B "$GIT_CHECKOUT_BRANCH_NAME" "$GIT_FETCH_TO___REF"

    git_submodule_update_recursive

    run cd "$OLDCWD"
}

git_submodule_update_recursive() {
    if [ -z "$1" ] ; then
        GIT_REPO_ROOT_DIR="$PWD"
    else
        GIT_REPO_ROOT_DIR="$1"
    fi

    GIT_SUBMODULE_HAVE="$(cd "$GIT_REPO_ROOT_DIR" && find . -type f -name '.gitmodules' -print -quit)"

    if [ -n "$GIT_SUBMODULE_HAVE" ] ; then
        if [ -z "$NDKPKG_URL_TRANSFORM" ] ; then
            run git submodule update --init --recursive
        else
            unset GIT_SUBMODULE_BASEDIR_STACK

            GIT_SUBMODULE_CONFIG_FILE_LIST="$(find "$GIT_REPO_ROOT_DIR" -type f -name '.gitmodules')"

            for f in $GIT_SUBMODULE_CONFIG_FILE_LIST
            do
                if [ -z "$GIT_SUBMODULE_BASEDIR_STACK" ] ; then
                    GIT_SUBMODULE_BASEDIR_STACK="${f%/*}"
                else
                    GIT_SUBMODULE_BASEDIR_STACK="$GIT_SUBMODULE_BASEDIR_STACK;${f%/*}"
                fi
            done

            while [ -n "$GIT_SUBMODULE_BASEDIR_STACK" ]
            do
                case $GIT_SUBMODULE_BASEDIR_STACK in
                    *\;*) GIT_SUBMODULE_BASEDIR="${GIT_SUBMODULE_BASEDIR_STACK##*;}" ; GIT_SUBMODULE_BASEDIR_STACK="${GIT_SUBMODULE_BASEDIR_STACK%;*}" ;;
                    *)    GIT_SUBMODULE_BASEDIR="${GIT_SUBMODULE_BASEDIR_STACK}"     ; GIT_SUBMODULE_BASEDIR_STACK=
                esac

                run cd "$GIT_SUBMODULE_BASEDIR"

                GIT_SUBMODULE_NAME_LIST="$(sed -n '/\[submodule ".*"\]/p' .gitmodules | sed 's|\[submodule "\(.*\)"\]|\1|')"

                for GIT_SUBMODULE_NAME in $GIT_SUBMODULE_NAME_LIST
                do
                    GIT_SUBMODULE_PATH="$(git config --file=.gitmodules --get "submodule.$GIT_SUBMODULE_NAME.path")"
                    GIT_SUBMODULE_URL="$(git config --file=.gitmodules --get "submodule.$GIT_SUBMODULE_NAME.url")"
                    GIT_SUBMODULE_URI="$("$NDKPKG_URL_TRANSFORM" "$GIT_SUBMODULE_URL")"

                    run git submodule set-url "$GIT_SUBMODULE_PATH" "$GIT_SUBMODULE_URI"
                done

                run git submodule update --init

                GIT_SUBMODULE_PATH_LIST="$(git submodule | sed 's|^ *||' | cut -d ' ' -f2)"

                for GIT_SUBMODULE_PATH in $GIT_SUBMODULE_PATH_LIST
                do
                    GIT_SUBMODULE_CONFIG_FILE_LIST="$(find "$GIT_SUBMODULE_PATH" -type f -name '.gitmodules')"

                    for f in $GIT_SUBMODULE_CONFIG_FILE_LIST
                    do
                        if [ -z "$GIT_SUBMODULE_BASEDIR_STACK" ] ; then
                            GIT_SUBMODULE_BASEDIR_STACK="$GIT_SUBMODULE_BASEDIR/${f%/*}"
                        else
                            GIT_SUBMODULE_BASEDIR_STACK="$GIT_SUBMODULE_BASEDIR_STACK;$GIT_SUBMODULE_BASEDIR/${f%/*}"
                        fi
                    done
                done
            done
        fi
    fi
}

# }}}
##############################################################################
# {{{ wfetch

# wfetch <URL> [--uri=<URL-MIRROR>] [--sha256=<SHA256>] [-o <OUTPUT-PATH>] [-q] [--no-buffer]
#
# If -o <OUTPUT-PATH> option is unspecified, the result will be written to <OUTPUT-PATH>/$(basename <URL>)
#
# If <OUTPUT-PATH> is -, then the result will be written to stdout.
#
# If <OUTPUT-PATH> is . .. or ends with slash(/), then it will be treated as a directory, otherwise, it will be treated as a filepath.
#
# If <OUTPUT-PATH> is treated as a directory, then it will be expanded to <OUTPUT-PATH>/$(basename <URL>)
#
# influential environment variable:
# NDKPKG_URL_TRANSFORM
wfetch() {
    unset FETCH_UTS
    unset FETCH_SHA

    unset FETCH_URL
    unset FETCH_URI

    unset FETCH_PATH

    unset FETCH_OUTPUT_DIR
    unset FETCH_OUTPUT_FILEPATH
    unset FETCH_OUTPUT_FILENAME

    unset FETCH_BUFFER_FILEPATH

    unset FETCH_SHA256_EXPECTED

    unset FETCH_SILENT

    unset NOT_BUFFER

    [ -z "$1" ] && abort 1 "wfetch <URL> [OPTION]... , <URL> must be non-empty."

    if [ -z "$NDKPKG_URL_TRANSFORM" ] ; then
        FETCH_URL="$1"
    else
        FETCH_URL="$("$NDKPKG_URL_TRANSFORM" "$1")" || return 1
    fi

    shift

    while [ -n "$1" ]
    do
        case $1 in
            --uri=*)
                FETCH_URI="${1#*=}"
                ;;
            --sha256=*)
                FETCH_SHA256_EXPECTED="${1#*=}"
                ;;
            -o) shift
                if [ -z "$1" ] ; then
                    abort 1 "wfetch <URL> -o <PATH> , <PATH> must be non-empty."
                else
                    FETCH_PATH="$1"
                fi
                ;;
            -q)
                FETCH_SILENT=1
                ;;
            --no-buffer)
                NOT_BUFFER=1
                ;;
            *)  abort 1 "wfetch <URL> [--uri=<URL-MIRROR>] [--sha256=<SHA256>] [-o <PATH>] [-q] , unrecognized option: $1"
        esac
        shift
    done

    if [ -z "$FETCH_URI" ] ; then
        # remove query params
        FETCH_URI="${FETCH_URL%%'?'*}"
        FETCH_URI="https://fossies.org/linux/misc/${FETCH_URI##*/}"
    else
        if [ -n "$NDKPKG_URL_TRANSFORM" ] ; then
            FETCH_URI="$("$NDKPKG_URL_TRANSFORM" "$FETCH_URI")" || return 1
        fi
    fi

    case $FETCH_PATH in
        -)
            FETCH_BUFFER_FILEPATH='-'
            ;;
        .|'')
            FETCH_OUTPUT_DIR='.'
            FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}"
            ;;
        ..)
            FETCH_OUTPUT_DIR='..'
            FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}"
            ;;
        */)
            FETCH_OUTPUT_DIR="${FETCH_PATH%/}"
            FETCH_OUTPUT_FILEPATH="$FETCH_OUTPUT_DIR/${FETCH_URL##*/}"
            ;;
        *)
            FETCH_OUTPUT_DIR="$(dirname "$FETCH_PATH")"
            FETCH_OUTPUT_FILEPATH="$FETCH_PATH"
    esac

    if [ -n "$FETCH_OUTPUT_FILEPATH" ] ; then
        if [ -f "$FETCH_OUTPUT_FILEPATH" ] ; then
            if [ -n "$FETCH_SHA256_EXPECTED" ] ; then
                if [ "$(sha256sum "$FETCH_OUTPUT_FILEPATH" | cut -d ' ' -f1)" = "$FETCH_SHA256_EXPECTED" ] ; then
                    success "$FETCH_OUTPUT_FILEPATH already have been fetched."
                    return 0
                fi
            fi
        fi

        if [ "$NOT_BUFFER" = 1 ] ; then
            FETCH_BUFFER_FILEPATH="$FETCH_OUTPUT_FILEPATH"
        else
            FETCH_UTS="$(date +%s)"

            FETCH_SHA="$(printf '%s\n' "$FETCH_URL:$$:$FETCH_UTS" | sha256sum | cut -d ' ' -f1)"

            FETCH_BUFFER_FILEPATH="$FETCH_OUTPUT_DIR/$FETCH_SHA.tmp"
        fi
    fi

    for FETCH_TOOL in curl wget http lynx aria2c axel
    do
        if command -v "$FETCH_TOOL" > /dev/null ; then
            break
        else
            unset FETCH_TOOL
        fi
    done

    if [ -z "$FETCH_TOOL" ] ; then
        abort 1 "none of curl wget http lynx aria2c axel command was found, please install one of them then try again."
    fi

    if [                -n "$FETCH_OUTPUT_DIR" ] ; then
        if [ !          -d "$FETCH_OUTPUT_DIR" ] ; then
            run install -d "$FETCH_OUTPUT_DIR" || return 1
        fi
    fi

    case $FETCH_TOOL in
        curl)
            unset CURL_OPTIONS

            if [ "$FETCH_SILENT" = 1 ] ; then
                CURL_OPTIONS='--no-progress-meter'
            fi

            if [ -n "$SSL_CERT_FILE" ] ; then
                CURL_OPTIONS="$CURL_OPTIONS --cacert $SSL_CERT_FILE"
            fi

            if [ -n "$NDKPKG_DNS_SERVERS" ] ; then
                CURL_OPTIONS="$CURL_OPTIONS --dns-servers $NDKPKG_DNS_SERVERS"
            fi

            run "curl $CURL_OPTIONS --fail --retry 20 --retry-delay 30 --location -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" ||
            run "curl $CURL_OPTIONS --fail --retry 20 --retry-delay 30 --location -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'"
            ;;
        wget)
            run "wget --timeout=60 -O '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" ||
            run "wget --timeout=60 -O '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'"
            ;;
        http)
            run "http --timeout=60 -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" ||
            run "http --timeout=60 -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'"
            ;;
        lynx)
            run "lynx -source '$FETCH_URL' > '$FETCH_BUFFER_FILEPATH'" ||
            run "lynx -source '$FETCH_URI' > '$FETCH_BUFFER_FILEPATH'"
            ;;
        aria2c)
            run "aria2c -d '$FETCH_OUTPUT_DIR' -o '$FETCH_OUTPUT_FILENAME' '$FETCH_URL'" ||
            run "aria2c -d '$FETCH_OUTPUT_DIR' -o '$FETCH_OUTPUT_FILENAME' '$FETCH_URI'"
            ;;
        axel)
            run "axel -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URL'" ||
            run "axel -o '$FETCH_BUFFER_FILEPATH' '$FETCH_URI'"
            ;;
        *)  abort 1 "wfetch() unimplementation: $FETCH_TOOL"
            ;;
    esac

    [ $? -eq 0 ] || return 1

    if [ -n "$FETCH_OUTPUT_FILEPATH" ] ; then
        if [ -n "$FETCH_SHA256_EXPECTED" ] ; then
            FETCH_SHA256_ACTUAL="$(sha256sum "$FETCH_BUFFER_FILEPATH" | cut -d ' ' -f1)"

            if [ "$FETCH_SHA256_ACTUAL" != "$FETCH_SHA256_EXPECTED" ] ; then
                abort 1 "sha256sum mismatch.\n    expect : $FETCH_SHA256_EXPECTED\n    actual : $FETCH_SHA256_ACTUAL\n"
            fi
        fi

        if [ "$NOT_BUFFER" != 1 ] ; then
            run mv "$FETCH_BUFFER_FILEPATH" "$FETCH_OUTPUT_FILEPATH"
        fi
    fi
}

# }}}
##############################################################################
# {{{ version

# check if match the condition
#
# condition:
# eq  equal
# ne  not equal
# gt  greater than
# lt  less than
# ge  greater than or equal
# le  less than or equal
#
# examples:
# version_match 1.15.3 eq 1.16.0
# version_match 1.15.3 lt 1.16.0
# version_match 1.15.3 gt 1.16.0
# version_match 1.15.3 le 1.16.0
# version_match 1.15.3 ge 1.16.0
version_match() {
    case $2 in
        eq)  [ "$1"  = "$3" ] ;;
        ne)  [ "$1" != "$3" ] ;;
        le)
            if [ "$1" = "$3" ] ; then
                return 0
            fi
            [ "$1" = "$(printf '%s\n' "$1" "$3" | sort -V | head -n 1)" ]
            ;;
        ge)
            if [ "$1" = "$3" ] ; then
                return 0
            fi
            [ "$1" = "$(printf '%s\n' "$1" "$3" | sort -V | tail -n 1)" ]
            ;;
        lt)
            if [ "$1" = "$3" ] ; then
                return 1
            fi
            [ "$1" = "$(printf '%s\n' "$1" "$3" | sort -V | head -n 1)" ]
            ;;
        gt)
            if [ "$1" = "$3" ] ; then
                return 1
            fi
            [ "$1" = "$(printf '%s\n' "$1" "$3" | sort -V | tail -n 1)" ]
            ;;
        *)  abort 1 "version_compare: $2: not supported operator."
    esac
}

xbuilder() {
    XBUILDER="$SESSION_DIR/xbuilder"

    if [ ! -f "$XBUILDER" ] ; then
        wfetch 'https://raw.githubusercontent.com/leleliu008/ppkg/refs/heads/master/xbuilder' -o "$XBUILDER" --no-buffer
    fi

    run sh "$XBUILDER" install "$@" --prefix="$NATIVE_PACKAGE_INSTALLED_ROOT" --download-dir="$NDKPKG_DOWNLOADS_DIR" --session-dir="$SESSION_DIR/native"
}

__install_the_given_package_onexit() {
    is_package_installed "$PACKAGE_SPEC" || {
        abort 1 "package installation failure: $PACKAGE_SPEC\n"

        if [ -n "$PACKAGE_WORKING_DIR"] ; then
            printf '%b\n' "${COLOR_RED}you would probably want to figure out want had happeded, please change to the working directory: $PACKAGE_WORKING_DIR${COLOR_OFF}"
        fi
    }
}

# Note: this function must run in a subshell
__install_the_given_package() {
    printf '%b\n' "${COLOR_PURPLE}>>> Installation ${COLOR_OFF}${COLOR_GREEN}${1}${COLOR_OFF}${COLOR_PURPLE} start${COLOR_OFF}"

    unset PACKAGE_WORKING_DIR

    trap  __install_the_given_package_onexit EXIT

    case $TARGET_PLATFORM_ARCH in
        armeabi-v7a)
            TARGET_PLATFORM_ABI='armeabi-v7a'
            TARGET_PLATFORM_ARCH='armv7a'
            TARGET_PLATFORM_NBIT=32
            ;;
        arm64-v8a)
            TARGET_PLATFORM_ABI='arm64-v8a'
            TARGET_PLATFORM_ARCH='aarch64'
            TARGET_PLATFORM_NBIT=64
            ;;
        x86)
            TARGET_PLATFORM_ABI='x86'
            TARGET_PLATFORM_ARCH='i686'
            TARGET_PLATFORM_NBIT=32
            ;;
        x86_64)
            TARGET_PLATFORM_ABI='x86_64'
            TARGET_PLATFORM_ARCH='x86_64'
            TARGET_PLATFORM_NBIT=64
            ;;
        *)  abort 1 "unsupported target arch: $TARGET_PLATFORM_ARCH"
    esac

    #########################################################################################

    if [ "$TARGET_PLATFORM_NBIT" -eq 64 ] ; then
        ANDROID_DYNAMIC_LINKER_PATH='/system/bin/linker64'
    else
        ANDROID_DYNAMIC_LINKER_PATH='/system/bin/linker'
    fi

    #########################################################################################

    if [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERBOSE" ] ; then
        cat <<EOF
      TIMESTAMP_UNIX = $TIMESTAMP_UNIX

NATIVE_PLATFORM_KIND = $NATIVE_PLATFORM_KIND
NATIVE_PLATFORM_TYPE = $NATIVE_PLATFORM_TYPE
NATIVE_PLATFORM_CODE = $NATIVE_PLATFORM_CODE
NATIVE_PLATFORM_NAME = $NATIVE_PLATFORM_NAME
NATIVE_PLATFORM_VERS = $NATIVE_PLATFORM_VERS
NATIVE_PLATFORM_ARCH = $NATIVE_PLATFORM_ARCH
NATIVE_PLATFORM_NCPU = $NATIVE_PLATFORM_NCPU
NATIVE_PLATFORM_LIBC = $NATIVE_PLATFORM_LIBC
NATIVE_PLATFORM_EUID = $NATIVE_PLATFORM_EUID
NATIVE_PLATFORM_EGID = $NATIVE_PLATFORM_EGID

TARGET_PLATFORM_VERS = $TARGET_PLATFORM_VERS
TARGET_PLATFORM_ARCH = $TARGET_PLATFORM_ARCH
TARGET_PLATFORM_ABI  = $TARGET_PLATFORM_ABI

NDKPKG_ARG0          = $NDKPKG_ARG0
NDKPKG_ARG1          = $NDKPKG_ARG1
NDKPKG_ARGV          = $NDKPKG_ARGV
NDKPKG_PATH          = $NDKPKG_PATH
NDKPKG_HOME          = $NDKPKG_HOME
NDKPKG_VERSION       = $NDKPKG_VERSION
NDKPKG_URL_TRANSFORM = $NDKPKG_URL_TRANSFORM

           LOG_LEVEL = $LOG_LEVEL
             PROFILE = $PROFILE

       ENABLE_CCACHE = $ENABLE_CCACHE
REQUEST_TO_KEEP_SESSION_DIR = $REQUEST_TO_KEEP_SESSION_DIR
REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON = $REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON
REQUEST_TO_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE = $REQUEST_TO_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE
EOF
    fi

    #########################################################################################

    step "load formula"

    PACKAGE_FORMULA_FILEPATH="$SESSION_DIR/$PACKAGE_NAME.yml"

    if [ "$DUMP_FORMULA" = 1 ] ; then
        bat --language=yaml --paging=never "$PACKAGE_FORMULA_FILEPATH"
    fi

    __load_formula_of_the_given_package "$PACKAGE_NAME" "$PACKAGE_FORMULA_FILEPATH"

    #########################################################################################

    unset PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE

    if [ "$REQUEST_TO_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE" = 1 ] ; then
        if [ "$PACKAGE_USE_BSYSTEM_GO" = 1 ] ; then
            note "You are requesting to create fully statically linked executables, but package '$PACKAGE_NAME' is a golang project and not supposed to create fully statically linked executables, so we will downgrade to create mostly statically linked executables. For more details, please read https://github.com/golang/go/issues/59942\n"
        else
            case $PACKAGE_PKGTYPE in
                exe)
                    PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE=1

                    if [ "$TARGET_PLATFORM_VERS" -ne "$ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL" ] ; then
                        abort 1 "You are requesting to create fully statically linked executables, but NDK only provide the libc.a for the latest Android API level $ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL. That's to say you're supposed to use Android API level $ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL to compile with this package. For more details, please read https://github.com/android/ndk/issues/2017"
                    fi
                    ;;
                pie)
                    note "You are requesting to create fully statically linked executables, but package '$PACKAGE_NAME' is supposed to create dynamically linked executables, so we will downgrade to create mostly statically linked executables."
            esac
        fi
    fi

    #########################################################################################

    if [ "$PACKAGE_PKGTYPE" != lib ] ; then
        export PACKAGE_CREATE_MOSTLY_STATICALLY_LINKED_EXECUTABLE=1
    else
        unset  PACKAGE_CREATE_MOSTLY_STATICALLY_LINKED_EXECUTABLE
    fi

    #########################################################################################

    if [ "$PACKAGE_PARALLEL" = 1 ] ; then
        BUILD_NJOBS="$NATIVE_PLATFORM_NCPU"
    else
        BUILD_NJOBS=1
    fi

    if [ -z "$PACKAGE_API_MIN" ] ; then
        PACKAGE_API_MIN="$ANDROID_NDK_SUPPORTED_MIN_SDK_API_LEVEL"
    fi

    if [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERBOSE" ] ; then
        cat <<EOF
supported min sdk api level: $PACKAGE_API_MIN
requested min sdk api level: $TARGET_PLATFORM_VERS
EOF
    fi

    if [ "$PACKAGE_API_MIN" -gt "$TARGET_PLATFORM_VERS" ] ; then
        abort 1 "package installation failure: '$1'\n    supported min sdk api level: $PACKAGE_API_MIN\n    requested min sdk api level: $TARGET_PLATFORM_VERS"
    fi

    #########################################################################################

    PACKAGE_INSTALL_UTS=
    PACKAGE_INSTALL_UTS="$(date +%s)"

    PACKAGE_INSTALL_SHA=
    PACKAGE_INSTALL_SHA="$(
{
    sha256sum <<EOF
$PACKAGE_SPEC:$$:$PACKAGE_INSTALL_UTS
EOF
} | cut -d ' ' -f1)"

    #########################################################################################

    PACKAGE_WORKING_DIR="$SESSION_DIR/$PACKAGE_SPEC"
    PACKAGE_BCACHED_DIR="$PACKAGE_WORKING_DIR/src/_"
    PACKAGE_INSTALL_DIR="$NDKPKG_PACKAGE_INSTALLED_ROOT/$TARGET_PLATFORM_SPEC/$PACKAGE_INSTALL_SHA"

    if [ -z "$PACKAGE_BSCRIPT" ] ; then
        PACKAGE_BSCRIPT_DIR="$PACKAGE_WORKING_DIR/src"
    else
        PACKAGE_BSCRIPT_DIR="$PACKAGE_WORKING_DIR/src/$PACKAGE_BSCRIPT"
    fi

    #########################################################################################

    [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERBOSE" ] && {
        cat <<EOF
PACKAGE_WORKING_DIR = $PACKAGE_WORKING_DIR
PACKAGE_BSCRIPT_DIR = $PACKAGE_BSCRIPT_DIR
PACKAGE_BCACHED_DIR = $PACKAGE_BCACHED_DIR
PACKAGE_INSTALL_DIR = $PACKAGE_INSTALL_DIR
EOF
}

    #########################################################################################

    step "create and change to the working directory"

    run install -d "$PACKAGE_WORKING_DIR"

    run cd "$PACKAGE_WORKING_DIR"

    run install -d src/_ fix res bin lib include

    #########################################################################################

    PACKAGE_INSTALLING_SRC_DIR="$PACKAGE_WORKING_DIR/src"
    PACKAGE_INSTALLING_FIX_DIR="$PACKAGE_WORKING_DIR/fix"
    PACKAGE_INSTALLING_RES_DIR="$PACKAGE_WORKING_DIR/res"
    PACKAGE_INSTALLING_BIN_DIR="$PACKAGE_WORKING_DIR/bin"
    PACKAGE_INSTALLING_LIB_DIR="$PACKAGE_WORKING_DIR/lib"
    PACKAGE_INSTALLING_INC_DIR="$PACKAGE_WORKING_DIR/include"

    #########################################################################################

    [ -n "$PACKAGE_ONSTART" ] && {
        step "onstart"

        eval "
onstart() {
$PACKAGE_ONSTART
}"
        onstart
    }

    #########################################################################################

    TOOLCHAIN_CONFIG_TARGET="$SESSION_DIR/toolchain-target.sh"

    if [ ! -f "$TOOLCHAIN_CONFIG_TARGET" ] ; then
        println_android_ndk_info > "$TOOLCHAIN_CONFIG_TARGET"
    fi

    #########################################################################################

    TOOLCHAIN_CONFIG_NATIVE="$SESSION_DIR/toolchain-native.sh"

    if [ -f "$TOOLCHAIN_CONFIG_NATIVE" ] ; then
        .   "$TOOLCHAIN_CONFIG_NATIVE"
    else
        step "locate C/C++ toolchain for native build"

        if [ "$NATIVE_PLATFORM_KIND" = 'darwin' ] ; then
                 CC_FOR_BUILD="$(xcrun --sdk macosx --find clang)"
               OBJC_FOR_BUILD="$(xcrun --sdk macosx --find clang)"
                CXX_FOR_BUILD="$(xcrun --sdk macosx --find clang++)"
                 AS_FOR_BUILD="$(xcrun --sdk macosx --find as)"
                 AR_FOR_BUILD="$(xcrun --sdk macosx --find ar)"
             RANLIB_FOR_BUILD="$(xcrun --sdk macosx --find ranlib)"
                 LD_FOR_BUILD="$(xcrun --sdk macosx --find ld)"
                 NM_FOR_BUILD="$(xcrun --sdk macosx --find nm)"
               SIZE_FOR_BUILD="$(xcrun --sdk macosx --find size)"
              STRIP_FOR_BUILD="$(xcrun --sdk macosx --find strip)"
            STRINGS_FOR_BUILD="$(xcrun --sdk macosx --find strings)"
            OBJDUMP_FOR_BUILD="$(xcrun --sdk macosx --find objdump)"
            SYSROOT_FOR_BUILD="$(xcrun --sdk macosx --show-sdk-path)"

            CCFLAGS_FOR_BUILD="-isysroot $SYSROOT_FOR_BUILD -mmacosx-version-min=$NATIVE_PLATFORM_VERS -arch $NATIVE_PLATFORM_ARCH -Qunused-arguments"
            LDFLAGS_FOR_BUILD='-Wl,-search_paths_first'
        else
                CXX_FOR_BUILD="$(command -v g++ || command -v clang++ || command -v c++)" || __install_gcc_via_syspm
                CXX_FOR_BUILD="$(command -v g++ || command -v clang++ || command -v c++)" || abort 1 "C++ Compiler for native not found."
                 CC_FOR_BUILD="$(command -v gcc || command -v clang   || command -v cc)"  || abort 1 "C Compiler for native not found."
               OBJC_FOR_BUILD="$(command -v gcc || command -v clang   || command -v cc)"  || abort 1 "C Compiler for native not found."
                 AS_FOR_BUILD="$(command -v as)"      || abort 1 "command not found: as"
                 AR_FOR_BUILD="$(command -v ar)"      || abort 1 "command not found: ar"
             RANLIB_FOR_BUILD="$(command -v ranlib)"  || abort 1 "command not found: ranlib"
                 LD_FOR_BUILD="$(command -v ld)"      || abort 1 "command not found: ld"
                 NM_FOR_BUILD="$(command -v nm)"      || abort 1 "command not found: nm"
               SIZE_FOR_BUILD="$(command -v size)"    || abort 1 "command not found: size"
              STRIP_FOR_BUILD="$(command -v strip)"   || abort 1 "command not found: strip"
            STRINGS_FOR_BUILD="$(command -v strings)" || abort 1 "command not found: strings"
            OBJDUMP_FOR_BUILD="$(command -v objdump)" || abort 1 "command not found: objdump"
            OBJCOPY_FOR_BUILD="$(command -v objcopy)" || abort 1 "command not found: objcopy"
            READELF_FOR_BUILD="$(command -v readelf)" || abort 1 "command not found: readelf"

            CCFLAGS_FOR_BUILD="-fPIC -fno-common"
            LDFLAGS_FOR_BUILD="-Wl,--as-needed -Wl,-z,muldefs -Wl,--allow-multiple-definition"
            #LDFLAGS_FOR_BUILD="-Wl,--as-needed -Wl,-z,muldefs -Wl,--allow-multiple-definition -fno-use-linker-plugin"
            # https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
        fi

        if [ "$DEBUG_CC" = 1 ] ; then
            CCFLAGS_FOR_BUILD="$CCFLAGS_FOR_BUILD -v"
        fi

        if [ "$DEBUG_LD" = 1 ] ; then
            LDFLAGS_FOR_BUILD="$LDFLAGS_FOR_BUILD -Wl,-v"
        fi

        if [ "$PROFILE" = release ] ; then
            CCFLAGS_FOR_BUILD="$CCFLAGS_FOR_BUILD -Os"
            LDFLAGS_FOR_BUILD="$LDFLAGS_FOR_BUILD -Wl,-S"
        fi

        cat > "$TOOLCHAIN_CONFIG_NATIVE" <<EOF
     CC_FOR_BUILD='$CC_FOR_BUILD'
   OBJC_FOR_BUILD='$OBJC_FOR_BUILD'
    CXX_FOR_BUILD='$CXX_FOR_BUILD'
     AS_FOR_BUILD='$AS_FOR_BUILD'
     AR_FOR_BUILD='$AR_FOR_BUILD'
 RANLIB_FOR_BUILD='$RANLIB_FOR_BUILD'
     LD_FOR_BUILD='$LD_FOR_BUILD'
     NM_FOR_BUILD='$NM_FOR_BUILD'
   SIZE_FOR_BUILD='$SIZE_FOR_BUILD'
  STRIP_FOR_BUILD='$STRIP_FOR_BUILD'
STRINGS_FOR_BUILD='$STRINGS_FOR_BUILD'
OBJDUMP_FOR_BUILD='$OBJDUMP_FOR_BUILD'
OBJCOPY_FOR_BUILD='$OBJCOPY_FOR_BUILD'
READELF_FOR_BUILD='$READELF_FOR_BUILD'
SYSROOT_FOR_BUILD='$SYSROOT_FOR_BUILD'

CCFLAGS_FOR_BUILD='$CCFLAGS_FOR_BUILD'
LDFLAGS_FOR_BUILD='$LDFLAGS_FOR_BUILD'
EOF
    fi

    export PROXIED_CC_FOR_BUILD="$CC_FOR_BUILD"
    export PROXIED_CXX_FOR_BUILD="$CXX_FOR_BUILD"
    export PROXIED_OBJC_FOR_BUILD="$OBJC_FOR_BUILD"

    export CCFLAGS_FOR_BUILD

     CC_FOR_BUILD="$NDKPKG_CORE_DIR/wrapper-native-cc"
   OBJC_FOR_BUILD="$NDKPKG_CORE_DIR/wrapper-native-objc"
    CXX_FOR_BUILD="$NDKPKG_CORE_DIR/wrapper-native-c++"
    CPP_FOR_BUILD="$CC_FOR_BUILD -E"

    #########################################################################################

    for TOOL in CC OBJC CXX CPP AS AR RANLIB LD NM STRIP SIZE STRINGS OBJDUMP OBJCOPY READELF SYSROOT CFLAGS OBJCFLAGS CXXFLAGS CPPFLAGS LDFLAGS
    do
        export "${TOOL}_FOR_BUILD"
        eval export "$TOOL=\"\$${TOOL}_FOR_BUILD\""
    done

    #########################################################################################

    PKG_CONFIG_PATH_FOR_BUILD="$NDKPKG_CORE_DIR/lib"

    #########################################################################################

    if [ "$PACKAGE_USE_BSYSTEM_CMAKE" = 1 ] ; then
        # https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html#manual:cmake-env-variables(7)

        unset CMAKE_APPBUNDLE_PATH
        unset CMAKE_FRAMEWORK_PATH
        unset CMAKE_PROGRAM_PATH
        unset CMAKE_INCLUDE_PATH
        unset CMAKE_LIBRARY_PATH
        unset CMAKE_PREFIX_PATH
        unset CMAKE_MAXIMUM_RECURSION_DEPTH
        unset CMAKE_APPLE_SILICON_PROCESSOR
        unset CMAKE_BUILD_PARALLEL_LEVEL
        unset CMAKE_BUILD_TYPE
        unset CMAKE_CONFIGURATION_TYPES
        unset CMAKE_CONFIG_TYPE
        unset CMAKE_EXPORT_COMPILE_COMMANDS
        unset CMAKE_GENERATOR
        unset CMAKE_GENERATOR_INSTANCE
        unset CMAKE_GENERATOR_PLATFORM
        unset CMAKE_GENERATOR_TOOLSET
        unset CMAKE_INSTALL_MODE
        unset CMAKE_C_COMPILER_LAUNCHER
        unset CMAKE_C_LINKER_LAUNCHER
        unset CMAKE_CXX_COMPILER_LAUNCHER
        unset CMAKE_CXX_LINKER_LAUNCHER
        unset CMAKE_MSVCIDE_RUN_PATH
        unset CMAKE_NO_VERBOSE
        unset CMAKE_OSX_ARCHITECTURES
        unset CMAKE_TOOLCHAIN_FILE
        unset DESTDIR
        unset VERBOSE
        unset CTEST_INTERACTIVE_DEBUG_MODE
        unset CTEST_OUTPUT_ON_FAILURE
        unset CTEST_PARALLEL_LEVEL
        unset CTEST_PROGRESS_OUTPUT
        unset CTEST_USE_LAUNCHERS_DEFAULT
        unset DASHBOARD_TEST_FROM_CTEST

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_BUILD_PARALLEL_LEVEL.html
        export CMAKE_BUILD_PARALLEL_LEVEL="$BUILD_NJOBS"

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_GENERATOR.html
        if [ "$PACKAGE_USE_BSYSTEM_NINJA" = 1 ] ; then
            export CMAKE_GENERATOR='Ninja'
        else
            export CMAKE_GENERATOR='Unix Makefiles'
        fi

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_EXPORT_COMPILE_COMMANDS.html
        if [ "$REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON" = 1 ] ; then
            export CMAKE_EXPORT_COMPILE_COMMANDS=ON
        else
            export CMAKE_EXPORT_COMPILE_COMMANDS=OFF
        fi

        case $PROFILE in
            debug)   CMAKE_BUILD_TYPE=Debug   ;;
            release) CMAKE_BUILD_TYPE=Release ;;
        esac

        if [ "$VERBOSE_CMAKE" = 1 ] ; then
            CMAKE_VERBOSE_MAKEFILE=ON
            CMAKE_COLOR_MAKEFILE=ON
            CMAKE_INSTALL_MESSAGE=ALWAYS
        else
            CMAKE_VERBOSE_MAKEFILE=OFF
            CMAKE_COLOR_MAKEFILE=OFF
            CMAKE_INSTALL_MESSAGE=NEVER
        fi

        # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_DEBUG_MODE.html
        if [ "$DEBUG_CMAKE" = 1 ] ; then
            CMAKE_FIND_DEBUG_MODE=ON
        else
            CMAKE_FIND_DEBUG_MODE=OFF
        fi
    fi

    #########################################################################################

    unset RECURSIVE_DEPENDENT_PACKAGE_NAMES

    [ -n "$PACKAGE_DEP_PKG" ] && {
        step "calculate dependency list of $1"

        unset PACKAGE_NAME_STACK

        for item in $PACKAGE_DEP_PKG
        do
            if [ -z "$item" ] ; then
                PACKAGE_NAME_STACK="$item"
            else
                PACKAGE_NAME_STACK="$PACKAGE_NAME_STACK;$item"
            fi
        done

        while [ -n "$PACKAGE_NAME_STACK" ]
        do
            case $PACKAGE_NAME_STACK in
                *\;*) TOPE="${PACKAGE_NAME_STACK##*;}" ; PACKAGE_NAME_STACK="${PACKAGE_NAME_STACK%;*}" ;;
                *)    TOPE="${PACKAGE_NAME_STACK}"     ; PACKAGE_NAME_STACK=
            esac

            RECURSIVE_DEPENDENT_PACKAGE_NAMES2="$TOPE"

            for item in $RECURSIVE_DEPENDENT_PACKAGE_NAMES
            do
                if [ "$item" != "$TOPE" ] ; then
                    RECURSIVE_DEPENDENT_PACKAGE_NAMES2="$RECURSIVE_DEPENDENT_PACKAGE_NAMES2 $item"
                fi
            done

            RECURSIVE_DEPENDENT_PACKAGE_NAMES="$RECURSIVE_DEPENDENT_PACKAGE_NAMES2"

            unset TOPE_UPPERCASE_UNDERSCORE
            TOPE_UPPERCASE_UNDERSCORE=$(printf '%s\n' "$TOPE" | tr '@+-.' '_' | tr a-z A-Z)

            for item in $(eval echo \$PACKAGE_DEP_PKG_"${TOPE_UPPERCASE_UNDERSCORE}")
            do
                if [ -z "$item" ] ; then
                    PACKAGE_NAME_STACK="$item"
                else
                    PACKAGE_NAME_STACK="$PACKAGE_NAME_STACK;$item"
                fi
            done
        done

        printf '%s\n' "$RECURSIVE_DEPENDENT_PACKAGE_NAMES"
    }

    #########################################################################################

    unset RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS

    [ -n "$PACKAGE_DEP_PKG" ] && {
        for DEPENDENT_PACKAGE_NAME in $RECURSIVE_DEPENDENT_PACKAGE_NAMES
        do
            DEPENDENT_PACKAGE_INSTALL_DIR="$NDKPKG_PACKAGE_INSTALLED_ROOT/$TARGET_PLATFORM_SPEC/$DEPENDENT_PACKAGE_NAME"

            if [ -z "$RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS" ] ; then
                RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS="$DEPENDENT_PACKAGE_INSTALL_DIR"
            else
                RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS="$RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS $DEPENDENT_PACKAGE_INSTALL_DIR"
            fi

            #########################################################################################

            DEPENDENT_PACKAGE_BINARY__DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/$DEPENDENT_PACKAGE_NAME/bin"

            if [ -d  "$DEPENDENT_PACKAGE_BINARY__DIR" ] ; then
                PATH="$DEPENDENT_PACKAGE_BINARY__DIR:$PATH"
            fi

            DEPENDENT_PACKAGE_BINARY__DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/$DEPENDENT_PACKAGE_NAME/sbin"

            if [ -d  "$DEPENDENT_PACKAGE_BINARY__DIR" ] ; then
                PATH="$DEPENDENT_PACKAGE_BINARY__DIR:$PATH"
            fi

            if [ -d          "$NATIVE_PACKAGE_INSTALLED_ROOT/$DEPENDENT_PACKAGE_NAME/share/aclocal" ] ; then
                ACLOCAL_PATH="$NATIVE_PACKAGE_INSTALLED_ROOT/$DEPENDENT_PACKAGE_NAME/share/aclocal:$ACLOCAL_PATH"
            fi
        done
    }

    #########################################################################################

    [ -n "$PACKAGE_DEP_PKG" ] && {
        step "generate  dependency tree of $1"

        unset DOT_CONTENT
        unset D2__CONTENT

        STACK="$PACKAGE_NAME"

        while [ -n "$STACK" ]
        do
            case $STACK in
                *\;*) TOPE="${STACK##*;}" ; STACK="${STACK%;*}" ;;
                *)    TOPE="${STACK}"     ; STACK=
            esac

            unset TOPE_UPPERCASE_UNDERSCORE
            TOPE_UPPERCASE_UNDERSCORE=$(printf '%s\n' "$TOPE" | tr '@+-.' '_' | tr a-z A-Z)

            TOPE_DEP_PKG="$(eval echo \$PACKAGE_DEP_PKG_"${TOPE_UPPERCASE_UNDERSCORE}")"

            if [ -n "$TOPE_DEP_PKG" ] ; then
                unset X; X="$(printf '"%s" ' $TOPE_DEP_PKG)"
                unset Y; Y="$(printf '    "%s" -> { %s}\n' "$TOPE" "$X")"

                if [ -z "$DOT_CONTENT" ] ; then
                    DOT_CONTENT="$Y"
                else
                    DOT_CONTENT="$(printf '%s\n%s\n' "$DOT_CONTENT" "$Y")"
                fi
            fi

            for item in $TOPE_DEP_PKG
            do
                if [ -z "$D2__CONTENT" ] ; then
                    D2__CONTENT="$TOPE -> $item"
                else
                    D2__CONTENT="$D2__CONTENT
$TOPE -> $item"
                fi

                if [ -z "$item" ] ; then
                    STACK="$item"
                else
                    STACK="$STACK;$item"
                fi
            done
        done

        DOT_CONTENT="digraph G {
$DOT_CONTENT
}"

        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

        PACKAGE_DEPENDENCY_GRAPH_FILEPATH_D2_="$PACKAGE_WORKING_DIR/dependencies.d2"
        PACKAGE_DEPENDENCY_GRAPH_FILEPATH_DOT="$PACKAGE_WORKING_DIR/dependencies.dot"
        PACKAGE_DEPENDENCY_GRAPH_FILEPATH_BOX="$PACKAGE_WORKING_DIR/dependencies.box"

        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

        printf '%s\n' "$D2__CONTENT" > "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_D2_"
        printf '%s\n' "$DOT_CONTENT" > "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_DOT"

        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

        # https://github.com/ggerganov/dot-to-ascii
        curl \
            -o "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_BOX" \
            -s \
            -G \
            --data-urlencode "boxart=1" \
            --data-urlencode "src=$DOT_CONTENT" \
            "https://dot-to-ascii.ggerganov.com/dot-to-ascii.php" || true

        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

        DOT="$(command -v dot || command -v dot_static || true)"

        if [ -n "$DOT" ] ; then
            run "$DOT" -Tsvg -o "$PACKAGE_WORKING_DIR/dependencies.svg" "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_DOT" || true
        else
            D2="$(command -v d2 || true)"

            if [ -n "$D2" ] ; then
                run "$D2" "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_D2_" "$PACKAGE_WORKING_DIR/dependencies.svg"
            fi
        fi

        #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#

        if [ -f "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_BOX" ] ; then
            cat "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_BOX"
        else
            cat "$PACKAGE_DEPENDENCY_GRAPH_FILEPATH_DOT"
        fi
    }

    #########################################################################################

    if [ "$PACKAGE_USE_BSYSTEM_GMAKE" = 1 ] && [ "$REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON" = 1 ] && [ "$BEAR_ENABLED" = 1 ] ; then
        PACKAGE_DEP_UPP="$PACKAGE_DEP_UPP bear"
    fi

    if [ "$ENABLE_CCACHE" = 1 ] ; then
        PACKAGE_DEP_UPP="$PACKAGE_DEP_UPP ccache"
    fi

    #########################################################################################

    unset PACKAGE_DEP_UPP_LIBZ
    unset PACKAGE_DEP_UPP_LIBOPENSSL
    unset PACKAGE_DEP_UPP_PYTHON3

    # these native packages are not relocatable and would be fetched to a fixed location /opt/non-relocatable-*
    unset PACKAGE_DEP_UPP_T2

    # these native packages would be built from source locally
    unset PACKAGE_DEP_XBUILDER

    #########################################################################################

    if [ "$TERMUX" = 1 ] ; then
        TERMUX_PKGS='pkg-config patchelf tree'

        for item in $PACKAGE_DEP_UPP
        do
            case $item in
                python3)  TERMUX_PKGS="$TERMUX_PKGS python" ;;
                libz)     TERMUX_PKGS="$TERMUX_PKGS zlib"   ;;
                *)        TERMUX_PKGS="$TERMUX_PKGS $item"  ;;
            esac
        done

        step "install needed packages via pkg"

        run pkg install -y "$TERMUX_PKGS"
    else
        step "install needed packages via uppm"

        run "$UPPM" about
        run "$UPPM" update

        unset UPPM_INSTALL_ARGS

        if [ "$DUMP_UPPM" = 1 ] ; then
            UPPM_INSTALL_ARGS=-v
        fi

        for UPPM_PACKAGE_NAME in $PACKAGE_DEP_UPP pkg-config patchelf tree
        do
            case $UPPM_PACKAGE_NAME in
                libz)
                    PACKAGE_DEP_UPP_LIBZ=1
                    PACKAGE_DEP_XBUILDER="$PACKAGE_DEP_XBUILDER libz"
                    continue
                    ;;
                libopenssl)
                    PACKAGE_DEP_UPP_LIBOPENSSL=1
                    PACKAGE_DEP_XBUILDER="$PACKAGE_DEP_XBUILDER libopenssl"
                    continue
                    ;;
                ruby)
                    PACKAGE_DEP_XBUILDER="$PACKAGE_DEP_XBUILDER ruby"
                    continue
                    ;;
                autotools)
                    PACKAGE_DEP_UPP_T2="$PACKAGE_DEP_UPP_T2 perl autoconf automake"
                    UPPM_PACKAGE_NAME=gm4
                    ;;
                perl|autoconf|automake|libtool|texinfo|help2man|intltool)
                    PACKAGE_DEP_UPP_T2="$PACKAGE_DEP_UPP_T2 $UPPM_PACKAGE_NAME"
                    continue
                    ;;
                python3)
                    PACKAGE_DEP_UPP_PYTHON3=1
                    continue
                    ;;
            esac

            run "$UPPM" install "$UPPM_PACKAGE_NAME" $UPPM_INSTALL_ARGS

            UPPM_PACKAGE_INSTALLED_DIR="$UPPM_HOME/installed/$UPPM_PACKAGE_NAME"

            if [ -d  "$UPPM_PACKAGE_INSTALLED_DIR/bin" ] ; then
                PATH="$UPPM_PACKAGE_INSTALLED_DIR/bin:$PATH"
            fi

            if [ -d  "$UPPM_PACKAGE_INSTALLED_DIR/sbin" ] ; then
                PATH="$UPPM_PACKAGE_INSTALLED_DIR/sbin:$PATH"
            fi

            if [ -d          "$UPPM_PACKAGE_INSTALLED_DIR/share/aclocal" ] ; then
                ACLOCAL_PATH="$UPPM_PACKAGE_INSTALLED_DIR/share/aclocal:$ACLOCAL_PATH"
            fi

            case $UPPM_PACKAGE_NAME in
                swig)
                    # https://www.swig.org/Doc4.0/Library.html
                    X="$(ls $UPPM_PACKAGE_INSTALLED_DIR/share/swig/*/swig.swg)"
                    export SWIG_LIB="${X%/*}"
                    ;;
                file)
                    export MAGIC="$UPPM_PACKAGE_INSTALLED_DIR/share/misc/magic.mgc"
                    ;;
                docbook-xsl)
                    # http://xmlsoft.org/xslt/xsltproc.html
                    export XML_CATALOG_FILES="$UPPM_PACKAGE_INSTALLED_DIR/catalog.xml"
                    printf '%s\n' "XML_CATALOG_FILES=$XML_CATALOG_FILES"
            esac
        done
    fi

    #########################################################################################

    [ -n "$PACKAGE_DEP_UPP_T2" ] && {
        if [ "$GITHUB_ACTIONS" = true ] ; then
            case $NATIVE_PLATFORM_TYPE in
                macos)
                    NATIVE_PLATFORM_VERS_MAJOR="${NATIVE_PLATFORM_VERS%%.*}"

                    if [ "$NATIVE_PLATFORM_VERS_MAJOR" -le 10 ] ; then
                        X='10.15'
                    elif [ "$NATIVE_PLATFORM_VERS_MAJOR" -ge 15 ] ; then
                        X='15.0'
                    else
                        X="$NATIVE_PLATFORM_VERS_MAJOR.0"
                    fi

                    T="macos-$X-$NATIVE_PLATFORM_ARCH"
                    ;;
                linux)
                    T="linux-$NATIVE_PLATFORM_LIBC-$NATIVE_PLATFORM_ARCH"
            esac

            NON_RELOCATEABLE_BINARY_PACKAGE_NAME="non-relocatable-binary-packages-2024.10.27-$T"
            NON_RELOCATEABLE_BINARY_PACKAGE_INSTALL_DIR="/opt/$NON_RELOCATEABLE_BINARY_PACKAGE_NAME"

            if [ ! -f "$NON_RELOCATEABLE_BINARY_PACKAGE_INSTALL_DIR/ok" ] ; then
                wfetch "https://github.com/leleliu008/non-relocatable-binary-packages/releases/download/2024.10.27/$NON_RELOCATEABLE_BINARY_PACKAGE_NAME.tar.xz"
                run $sudo install -d -g `id -g` -o `id -u` "$NON_RELOCATEABLE_BINARY_PACKAGE_INSTALL_DIR"
                run bsdtar xPf "$NON_RELOCATEABLE_BINARY_PACKAGE_NAME.tar.xz"
                run touch "$NON_RELOCATEABLE_BINARY_PACKAGE_INSTALL_DIR/ok"
            fi

            export PATH="$NON_RELOCATEABLE_BINARY_PACKAGE_INSTALL_DIR/bin:$PATH"
        else
            PACKAGE_DEP_XBUILDER="$PACKAGE_DEP_XBUILDER $PACKAGE_DEP_UPP_T2"
        fi
    }

    #########################################################################################

    [ -n "$PACKAGE_DEP_XBUILDER" ] && {
        run "$UPPM" install gmake

        export PATH="$UPPM_HOME/installed/gmake/bin:$PATH"

        xbuilder "$PACKAGE_DEP_XBUILDER"

        for NATIVE_PACKAGE_NAME in $PACKAGE_DEP_XBUILDER
        do
            NATIVE_PACKAGE_INSTALLED_DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/$NATIVE_PACKAGE_NAME"

            if [ -d  "$NATIVE_PACKAGE_INSTALLED_DIR/include" ] ; then
                CPPFLAGS_FOR_BUILD="$CPPFLAGS_FOR_BUILD -I$NATIVE_PACKAGE_INSTALLED_DIR/include"
            fi

            if [ -d  "$NATIVE_PACKAGE_INSTALLED_DIR/lib" ] ; then
                LDFLAGS_FOR_BUILD="$LDFLAGS_FOR_BUILD -L$NATIVE_PACKAGE_INSTALLED_DIR/lib -Wl,-rpath,$NATIVE_PACKAGE_INSTALLED_DIR/lib"
            fi

            if [ -d  "$NATIVE_PACKAGE_INSTALLED_DIR/bin" ] ; then
                PATH="$NATIVE_PACKAGE_INSTALLED_DIR/bin:$PATH"
            fi

            if [ -d  "$NATIVE_PACKAGE_INSTALLED_DIR/sbin" ] ; then
                PATH="$NATIVE_PACKAGE_INSTALLED_DIR/sbin:$PATH"
            fi

            if [ -d          "$NATIVE_PACKAGE_INSTALLED_DIR/share/aclocal" ] ; then
                ACLOCAL_PATH="$NATIVE_PACKAGE_INSTALLED_DIR/share/aclocal:$ACLOCAL_PATH"
            fi
        done
    }

    #########################################################################################

    [ "$PACKAGE_DEP_UPP_PYTHON3" = 1 ] && {
        case $NATIVE_PLATFORM_TYPE in
            macos)
                NATIVE_PLATFORM_VERS_MAJOR="${NATIVE_PLATFORM_VERS%%.*}"

                if [ "$NATIVE_PLATFORM_VERS_MAJOR" -le 10 ] ; then
                    X='10.15'
                elif [ "$NATIVE_PLATFORM_VERS_MAJOR" -ge 15 ] ; then
                    X='15.0'
                else
                    X="$NATIVE_PLATFORM_VERS_MAJOR.0"
                fi

                T="macos-$X-$NATIVE_PLATFORM_ARCH"
                ;;
            linux)
                T="linux-$NATIVE_PLATFORM_LIBC-$NATIVE_PLATFORM_ARCH"
        esac

        PYTHON3_DISTRIBUTION_FILENAME_PREFIX="python-distribution-2024.10.27-$T"
        PYTHON3_DISTRIBUTION_INSTALL_DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/python3"

        if [ ! -f "$PYTHON3_DISTRIBUTION_INSTALL_DIR/ok" ] ; then
            wfetch "https://github.com/leleliu008/python-distribution/releases/download/2024.10.27/$PYTHON3_DISTRIBUTION_FILENAME_PREFIX.tar.xz"
            run install -d "$PYTHON3_DISTRIBUTION_INSTALL_DIR"
            run bsdtar xf  "$PYTHON3_DISTRIBUTION_FILENAME_PREFIX.tar.xz" -C "$PYTHON3_DISTRIBUTION_INSTALL_DIR" --strip-components=1
            run touch "$PYTHON3_DISTRIBUTION_INSTALL_DIR/ok"
        fi

        export PATH="$PYTHON3_DISTRIBUTION_INSTALL_DIR/bin:$PATH"
    }

    #########################################################################################

    [ -n "$PACKAGE_DEP_PYM" ] && {
        step "install needed python packages via pip"

        PYTHON3="$(command -v python3)" || abort 1 "command not found: python3"

        run "$PYTHON3" --version
        run "$PYTHON3" -m pip install --upgrade pip
        run "$PYTHON3" -m pip install --upgrade "$PACKAGE_DEP_PYM"
    }

    #########################################################################################

    # cpan use the C/C++ compiler same as perl was built with
    # so make sure C/C++ compiler be found before reaching here

    [ -n "$PACKAGE_DEP_PLM" ] && {
        step "install needed perl modules via cpan"

        unset PACKAGE_DEP_PLM_T1
        unset PACKAGE_DEP_PLM_T2

        for item in $PACKAGE_DEP_PLM
        do
            if [ "$item" = 'XML::Parser' ] ; then
                PACKAGE_DEP_PLM_T1='XML::Parser'
            else
                PACKAGE_DEP_PLM_T2="$PACKAGE_DEP_PLM_T2 $item"
            fi
        done

        if [ -n "$PACKAGE_DEP_PLM_T1" ] ; then
            xbuilder perl_XML_Parser
        fi

        if [ -n "$PACKAGE_DEP_PLM_T2" ] ; then
            PACKAGE_DEP_PLM_T2="${PACKAGE_DEP_PLM_T2# }"
        fi

        if [ -n "$PACKAGE_DEP_PLM_T2" ] ; then
            # Would you like to configure as much as possible automatically? [yes]
            # https://perldoc.perl.org/cpan#PERL_MM_USE_DEFAULT
            export PERL_MM_USE_DEFAULT=1
            run cpan "$PACKAGE_DEP_PLM_T2"
        fi

        if [ -d "$HOME/perl5/bin" ] ; then
            # cpan install to default local location
            bppend_to_PATH "$HOME/perl5/bin"
        fi
    }

    #########################################################################################

    [ "$PACKAGE_USE_BSYSTEM_CARGO" = 1 ] && {
        command -v rustup > /dev/null || {
            # https://www.rust-lang.org/tools/install
            note "${COLOR_GREEN}rustup cargo rustc${COLOR_OFF} ${COLOR_YELLOW}commands are required, but it was not found, let's install it.${COLOR_OFF}"

            wfetch 'https://sh.rustup.rs' -o rustup-init.sh --no-buffer

            run bash rustup-init.sh -y
        }
    }

    #########################################################################################

    step "locate needed tools"

    unset AUTORECONF
    unset AUTOCONF
    unset AUTOMAKE
    unset ACLOCAL
    unset PERL
    unset M4

    unset MESON
    unset CMAKE
    unset XMAKE
    unset GMAKE
    unset NINJA

    unset BEAR
    unset CCACHE
    unset PKG_CONFIG

    if [ "$PACKAGE_USE_BSYSTEM_AUTOGENSH" = 1 ] || [ "$PACKAGE_USE_BSYSTEM_AUTOTOOLS" = 1 ] ; then
        AUTORECONF=$(command -v autoreconf) || abort 1 "command not found: autoreconf"
        AUTOCONF=$(command -v autoconf)     || abort 1 "command not found: autoconf"
        AUTOMAKE=$(command -v automake)     || abort 1 "command not found: automake"
        ACLOCAL=$(command -v aclocal)       || abort 1 "command not found: aclocal"
        PERL=$(command -v perl)             || abort 1 "command not found: perl"
        M4=$(command -v m4)                 || abort 1 "command not found: m4"
    fi

    [ "$PACKAGE_USE_BSYSTEM_MESON" = 1 ] && {
        MESON=$(command -v meson) || abort 1 "command not found: meson"
    }

    [ "$PACKAGE_USE_BSYSTEM_CMAKE" = 1 ] && {
        CMAKE=$(command -v cmake) || abort 1 "command not found: cmake"
    }

    [ "$PACKAGE_USE_BSYSTEM_XMAKE" = 1 ] && {
        XMAKE=$(command -v xmake) || abort 1 "command not found: xmake"

        # error: Running xmake as root is extremely dangerous and no longer supported.
        # As xmake does not drop privileges on installation you would be giving all
        # build scripts full access to your system.
        # Or you can add `--root` option or XMAKE_ROOT=y to allow run as root temporarily.
        export XMAKE_ROOT=y
    }

    [ "$PACKAGE_USE_BSYSTEM_GMAKE" = 1 ] && {
        GMAKE=$(command -v gmake || command -v make) || abort 1 "command not found: gmake and make"
    }

    [ "$PACKAGE_USE_BSYSTEM_NINJA" = 1 ] && {
        NINJA=$(command -v ninja) || abort 1 "command not found: ninja"
    }

    [ "$PACKAGE_USE_BSYSTEM_CARGO" = 1 ] && {
        RUSTUP=$(command -v rustup) || abort 1 "command not found: rustup"
        CARGO=$(command -v cargo)   || abort 1 "command not found: cargo"
    }

    [ "$PACKAGE_USE_BSYSTEM_GO" = 1 ] && {
        GO=$(command -v go) || abort 1 "command not found: go"
    }

    [ "$ENABLE_CCACHE" = 1 ] && {
        CCACHE=$(command -v ccache) || abort 1 "command not found: ccache"
    }

    PKG_CONFIG=$(command -v pkg-config || command -v pkgconf) || abort 1 "command not found: pkg-config"

    unset  M4
    export M4="$(command -v m4 || true)"

    PATCHELF=$(command -v patchelf) || abort 1 "command not found: patchelf"

    TREE=$(command -v tree) || abort 1 "command not found: tree"

    #########################################################################################

    step "fetching resources"

    case $PACKAGE_SRC_URL in
        '')
            if [ -n "$PACKAGE_GIT_URL" ] ; then
                unset GIT_FETCH_URL

                if [ -z "$NDKPKG_URL_TRANSFORM" ] ; then
                    GIT_FETCH_URL="$PACKAGE_GIT_URL"
                else
                    GIT_FETCH_URL="$("$NDKPKG_URL_TRANSFORM" "$PACKAGE_GIT_URL")" || return 1
                fi

                if [ -z "$PACKAGE_GIT_SHA" ] ; then
                    if [ -z "$PACKAGE_GIT_REF" ] ; then
                        GIT_BRANCH_NAME=master
                        GIT_REF_SPEC="+HEAD:refs/remotes/origin/master"
                    else
                        GIT_BRANCH_NAME="$(basename "$PACKAGE_GIT_REF")"
                        GIT_REF_SPEC="+$PACKAGE_GIT_REF:refs/remotes/origin/$GIT_BRANCH_NAME"
                    fi
                else
                    GIT_BRANCH_NAME=master
                    GIT_REF_SPEC="+$PACKAGE_GIT_SHA:refs/remotes/origin/master"
                fi

                if [ -z "$PACKAGE_GIT_NTH" ] ; then
                    PACKAGE_GIT_NTH=1
                fi

                if [ "$PACKAGE_GIT_NTH" -eq 0 ] ; then
                    if [ -f "$PACKAGE_SRC_FILEPATH/.git/shallow" ] ; then
                        GIT_FETCH_EXTRA_OPTIONS='--unshallow'
                    else
                        GIT_FETCH_EXTRA_OPTIONS=
                    fi
                else
                    GIT_FETCH_EXTRA_OPTIONS="--depth=$PACKAGE_GIT_NTH"
                fi

                run cd "$PACKAGE_INSTALLING_SRC_DIR"

                run git -c init.defaultBranch=master init
                run git remote add origin "$GIT_FETCH_URL"
                run git -c protocol.version=2 fetch --progress $GIT_FETCH_EXTRA_OPTIONS origin "$GIT_REF_SPEC"
                run git checkout --progress --force -B "$GIT_BRANCH_NAME" "refs/remotes/origin/$GIT_BRANCH_NAME"

                git_submodule_update_recursive
            fi
            ;;
        dir://*)
            note "$PACKAGE_SRC_URL is local path, no need to fetch."
            ;;
        file://*)
            note "$PACKAGE_SRC_URL is local path, no need to fetch."
            ;;
        *)  wfetch "$PACKAGE_SRC_URL" --uri="$PACKAGE_SRC_URI" --sha256="$PACKAGE_SRC_SHA" -o "$PACKAGE_SRC_FILEPATH"
    esac

    if [ -n    "$PACKAGE_FIX_URL" ] ; then
        wfetch "$PACKAGE_FIX_URL" --uri="$PACKAGE_FIX_URI" --sha256="$PACKAGE_FIX_SHA" -o "$PACKAGE_FIX_FILEPATH"
    fi

    if [ -n    "$PACKAGE_RES_URL" ] ; then
        wfetch "$PACKAGE_RES_URL" --uri="$PACKAGE_RES_URI" --sha256="$PACKAGE_RES_SHA" -o "$PACKAGE_RES_FILEPATH"
    fi

    #########################################################################################

    step "unpack/copy resources to proper location"

    if [ -n "$PACKAGE_SRC_FILEPATH" ] ; then
        case $PACKAGE_SRC_FILETYPE in
            .dir)
                if [ -d "$PACKAGE_SRC_FILEPATH" ] ; then
                    if [ -d "$PACKAGE_SRC_FILEPATH/.git" ] && command -v git > /dev/null ; then
                        PACKAGE_GIT_SHA=$(git -C "$PACKAGE_SRC_FILEPATH" rev-parse HEAD || true)
                    fi
                    run cp -r "$PACKAGE_SRC_FILEPATH/." "$PACKAGE_INSTALLING_SRC_DIR"
                else
                    abort 1 "src-url point to dir '$PACKAGE_SRC_FILEPATH' does not exist."
                fi
                ;;
            .git)
                if [ -z "$PACKAGE_GIT_SHA" ] ; then
                    PACKAGE_GIT_SHA="$(git rev-parse HEAD)"
                fi
                ;;
            .zip|.txz|.tgz|.tlz|.tbz2|.crate)
                run bsdtar xf "$PACKAGE_SRC_FILEPATH" -C "$PACKAGE_INSTALLING_SRC_DIR" --strip-components 1 --no-same-owner
                ;;
            *)  run cp "$PACKAGE_SRC_FILEPATH" "$PACKAGE_INSTALLING_SRC_DIR/"
        esac
    fi

    if [ -n "$PACKAGE_FIX_FILEPATH" ] ; then
        case $PACKAGE_FIX_FILETYPE in
            .zip|.txz|.tgz|.tlz|.tbz2|.crate)
                run bsdtar xf "$PACKAGE_FIX_FILEPATH" -C "$PACKAGE_INSTALLING_FIX_DIR" --strip-components 1 --no-same-owner
                ;;
            *)  run cp "$PACKAGE_FIX_FILEPATH" "$PACKAGE_INSTALLING_FIX_DIR/"
                printf '%s|%s\n' "$PACKAGE_FIX_FILENAME" "$PACKAGE_FIX_OPT" > "$PACKAGE_INSTALLING_FIX_DIR/index"
        esac
    fi

    if [ -n "$PACKAGE_RES_FILEPATH" ] ; then
        case $PACKAGE_RES_FILETYPE in
            .zip|.txz|.tgz|.tlz|.tbz2|.crate)
                run bsdtar xf "$PACKAGE_RES_FILEPATH" -C "$PACKAGE_INSTALLING_RES_DIR" --strip-components 1 --no-same-owner
                ;;
            *)  run cp "$PACKAGE_RES_FILEPATH" "$PACKAGE_INSTALLING_RES_DIR/"
        esac
    fi

    for LINE in $PACKAGE_PATCHES
    do
        SHA="$(printf '%s\n' "$LINE" | cut -d '|' -f1)"
        URL="$(printf '%s\n' "$LINE" | cut -d '|' -f2)"
        URI="$(printf '%s\n' "$LINE" | cut -d '|' -f3)"
        OPT="$(printf '%s\n' "$LINE" | cut -d '|' -f4)"

        FILETYPE="$(filetype_from_url "$URL")"
        FILENAME="$SHA$FILETYPE"
        FILEPATH="$NDKPKG_DOWNLOADS_DIR/$FILENAME"

        wfetch "$URL" --uri="$URI" --sha256="$SHA" -o "$FILEPATH"

        case $FILETYPE in
            .zip|.txz|.tgz|.tlz|.tbz2|.crate)
                run bsdtar xf "$FILEPATH" -C "$PACKAGE_INSTALLING_FIX_DIR" --strip-components 1 --no-same-owner
                ;;
            *)  run cp "$FILEPATH" "$PACKAGE_INSTALLING_FIX_DIR/"
                printf '%s|%s\n' "$FILENAME" "$OPT" >> "$PACKAGE_INSTALLING_FIX_DIR/index"
        esac
    done

    for LINE in $PACKAGE_RESLIST
    do
        SHA="$(printf '%s\n' "$LINE" | cut -d '|' -f1)"
        URL="$(printf '%s\n' "$LINE" | cut -d '|' -f2)"
        URI="$(printf '%s\n' "$LINE" | cut -d '|' -f3)"
        DIR="$(printf '%s\n' "$LINE" | cut -d '|' -f4)"
        LEV="$(printf '%s\n' "$LINE" | cut -d '|' -f5)"

        [ -z "$LEV" ] && LEV=1

        FILETYPE="$(filetype_from_url "$URL")"
        FILENAME="$SHA$FILETYPE"
        FILEPATH="$NDKPKG_DOWNLOADS_DIR/$FILENAME"

        wfetch "$URL" --uri="$URI" --sha256="$SHA" -o "$FILEPATH"

        if [ -z "$DIR" ] ; then
            DEST="$PACKAGE_INSTALLING_RES_DIR"
        else
            DEST="$PACKAGE_INSTALLING_RES_DIR/$DIR"
            run install -d "$DEST"
        fi

        case $FILETYPE in
            .zip|.txz|.tgz|.tlz|.tbz2|.crate)
                run bsdtar xf "$FILEPATH" -C "$DEST" --strip-components "$LEV" --no-same-owner
                ;;
            *)  run cp "$FILEPATH" "$DEST/"
        esac
    done

    #########################################################################################

    [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERBOSE" ] && {
        step "tree files of the installing top directory"
        run tree --dirsfirst -L 2 "$PACKAGE_WORKING_DIR"

        step "list files of the installing src directory"
        run ls -l "$PACKAGE_INSTALLING_SRC_DIR"

        if [ -n "$PACKAGE_BSCRIPT" ] ; then
            step "list files of the installing build script directory"
            run ls -l "$PACKAGE_BSCRIPT_DIR"
        fi
    }

    #########################################################################################

    # https://www.gnu.org/software/gettext/manual/html_node/config_002eguess.html
    # https://git.savannah.gnu.org/cgit/config.git/tree/

    step "update config.{sub,guess}"

    {
        [ "$PACKAGE_USE_BSYSTEM_AUTOGENSH" = 1 ] ||
        [ "$PACKAGE_USE_BSYSTEM_AUTOTOOLS" = 1 ] ||
        [ "$PACKAGE_USE_BSYSTEM_CONFIGURE" = 1 ]
    } && {
        for FILENAME in config.sub config.guess
        do
            FILEPATH="$SESSION_DIR/$FILENAME"

            [ -f "$FILEPATH" ] || {
                wfetch "https://git.savannah.gnu.org/cgit/config.git/plain/$FILENAME" -o "$FILEPATH"

                run chmod a+x "$FILEPATH"

                if [ "$FILENAME" = 'config.sub' ] ; then
                    gsed -i 's/arm64-*/arm64-*|arm64e-*/g' "$FILEPATH"
                fi
            }

            find "$PACKAGE_BSCRIPT_DIR" -name "$FILENAME" -exec cp -vf "$FILEPATH" {} \;
        done
    }

    #########################################################################################

    if [ -n "$PACKAGE_ONREADY" ] ; then
        step "onready"

        if [ "$PWD" != "$PACKAGE_BSCRIPT_DIR" ] ; then
            run     cd "$PACKAGE_BSCRIPT_DIR"
        fi

        eval "
onready() {
$PACKAGE_ONREADY
}"
        onready
    fi

    #########################################################################################

    if [ -n "$PACKAGE_DO12345" ] ; then
        step "install for native"

        NATIVE_BUILD_NEEDED=1

        NATIVE_INSTALLED_VERSION_TXT_FILEPATH="$NATIVE_PACKAGE_INSTALLED_ROOT/$PACKAGE_NAME/version.txt"

        [ -f "$NATIVE_INSTALLED_VERSION_TXT_FILEPATH" ] && {
            if [ "$(cat "$NATIVE_INSTALLED_VERSION_TXT_FILEPATH")" = "$PACKAGE_VERSION" ] ; then
                NATIVE_BUILD_NEEDED=0
                note "install for native already have been done, skipped."
            else
                note "install for native already have been done, but not the same version, rebuild it."
            fi
        }

        if [ "$NATIVE_BUILD_NEEDED" = 1 ] ; then
            NATIVE_BCACHED_DIR="$PACKAGE_WORKING_DIR/src/-"
            NATIVE_INSTALL_DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/$PACKAGE_INSTALL_SHA"

            cat <<EOF
NATIVE_BCACHED_DIR = $NATIVE_BCACHED_DIR
NATIVE_INSTALL_DIR = $NATIVE_INSTALL_DIR
EOF

            (
                PACKAGE_BCACHED_DIR="$NATIVE_BCACHED_DIR"
                PACKAGE_INSTALL_DIR="$NATIVE_INSTALL_DIR"

                run install -d "$PACKAGE_BCACHED_DIR"

                if [ "$PACKAGE_BINBSTD" = 1 ] ; then
                    run cd "$PACKAGE_BSCRIPT_DIR"
                else
                    run cd "$PACKAGE_BCACHED_DIR"
                fi

                [ "$DUMP_ENV" = 1 ] && {
                    run export -p
                    echo
                }

                eval "
build_for_native() {
$PACKAGE_DO12345
}"

                BUILD_FOR_NATIVE=1

                build_for_native
            )

            [ -d "$NATIVE_INSTALL_DIR" ] && {
                printf '%s\n' "$PACKAGE_VERSION" > "$NATIVE_INSTALL_DIR/version.txt"
                run ln -s -r -f -T "$NATIVE_INSTALL_DIR" "$NATIVE_PACKAGE_INSTALLED_ROOT/$PACKAGE_NAME"
            }
        else
            NATIVE_INSTALL_DIR="$NATIVE_PACKAGE_INSTALLED_ROOT/$PACKAGE_NAME"
        fi

        [ -d "$NATIVE_INSTALL_DIR" ] && {
            if [ -d  "$NATIVE_INSTALL_DIR/bin" ] ; then
                PATH="$NATIVE_INSTALL_DIR/bin:$PATH"
            fi

            if [ -d  "$NATIVE_INSTALL_DIR/sbin" ] ; then
                PATH="$NATIVE_INSTALL_DIR/sbin:$PATH"
            fi

            if [ -d          "$NATIVE_INSTALL_DIR/share/aclocal" ] ; then
                ACLOCAL_PATH="$NATIVE_INSTALL_DIR/share/aclocal:$ACLOCAL_PATH"
            fi
        }
    fi

    #########################################################################################
    #                            below is for target                                        #
    #########################################################################################

    if [ "$TARGET_PLATFORM_ARCH" = armv7a ] ; then
        TARGET_TRIPLE='armv7a-linux-androideabi'
    else
        TARGET_TRIPLE="$TARGET_PLATFORM_ARCH-linux-android"
    fi

    export ANDROID_NDK_COMPILER_ARGS="--target=${TARGET_TRIPLE}${TARGET_PLATFORM_VERS} --sysroot=$ANDROID_NDK_SYSROOT"

    export ANDROID_NDK_CC
    export ANDROID_NDK_CXX

    #########################################################################################

    export      CC="$NDKPKG_CORE_DIR/wrapper-target-cc"
    export     CXX="$NDKPKG_CORE_DIR/wrapper-target-c++"
    export     CPP="$CC -E"
    export      LD="$ANDROID_NDK_LD"
    export      AS="$ANDROID_NDK_AS"
    export      AR="$ANDROID_NDK_AR"
    export      NM="$ANDROID_NDK_NM"
    export    SIZE="$ANDROID_NDK_SIZE"
    export   STRIP="$ANDROID_NDK_STRIP"
    export  RANLIB="$ANDROID_NDK_RANLIB"
    export STRINGS="$ANDROID_NDK_STRINGS"
    export OBJDUMP="$ANDROID_NDK_OBJDUMP"
    export OBJCOPY="$ANDROID_NDK_OBJCOPY"
    export READELF="$ANDROID_NDK_READELF"
    export SYSROOT="$ANDROID_NDK_SYSROOT"

    #########################################################################################

    NDKPKG_COMMON_H_FILEPATH="$PACKAGE_INSTALLING_INC_DIR/ndk-pkg-common.h"

    #########################################################################################

    # https://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/Warning-Options.html
    CCFLAGS="-Qunused-arguments -fPIC -Wall"
    XXFLAGS="-Qunused-arguments -fPIC -Wall"
    PPFLAGS="-Qunused-arguments -include $NDKPKG_COMMON_H_FILEPATH"
    LDFLAGS="-Wl,--as-needed -Wl,-z,muldefs -Wl,--allow-multiple-definition"

    CCFLAGS="$CCFLAGS $PACKAGE_CCFLAGS"
    XXFLAGS="$XXFLAGS $PACKAGE_XXFLAGS"
    PPFLAGS="$PPFLAGS $PACKAGE_PPFLAGS"
    LDFLAGS="$LDFLAGS $PACKAGE_LDFLAGS"

    ##############################################

    _F_COMMON_OPT_IS_SET=0

    for item in $PACKAGE_CCFLAGS
    do
        [ "$item" = '-fcommon' ] && {
            _F_COMMON_OPT_IS_SET=1
            break
        }
    done

    if [ "$_F_COMMON_OPT_IS_SET" = 0 ] ; then
        CCFLAGS="$CCFLAGS -fno-common"
    fi

    ##############################################

    _F_COMMON_OPT_IS_SET=0

    for item in $PACKAGE_XXFLAGS
    do
        [ "$item" = '-fcommon' ] && {
            _F_COMMON_OPT_IS_SET=1
            break
        }
    done

    if [ "$_F_COMMON_OPT_IS_SET" = 0 ] ; then
        XXFLAGS="$XXFLAGS -fno-common"
    fi

    ##############################################

    CCFLAGS="$(printf '%s\n' "$CCFLAGS" | sed -e 's|--static||g' -e 's|-static||g')"
    XXFLAGS="$(printf '%s\n' "$XXFLAGS" | sed -e 's|--static||g' -e 's|-static||g')"
    LDFLAGS="$(printf '%s\n' "$LDFLAGS" | sed -e 's|--static||g' -e 's|-static||g')"

    ##############################################

    if [ "$PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE" = 1 ] ; then
        LDFLAGS="-static --static -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--no-dynamic-linker $LDFLAGS"
    fi

    ##############################################

    if [ "$DEBUG_CC" = 1 ] ; then
        CCFLAGS="$CCFLAGS -v"
        XXFLAGS="$XXFLAGS -v"
    fi

    if [ "$DEBUG_LD" = 1 ] ; then
        LDFLAGS="$LDFLAGS -Wl,-v"
    fi

    ##############################################

    case $PROFILE in
        debug)
            CCFLAGS="$CCFLAGS -O0 -g"
            XXFLAGS="$XXFLAGS -O0 -g"
            ;;
        release)
            CCFLAGS="$CCFLAGS -Os"
            XXFLAGS="$XXFLAGS -Os"

            unset _U_NDEBUG_OPT_IS_SET

            for item in $PACKAGE_PPFLAGS
            do
                [ "$item" = '-UNDEBUG' ] && {
                    _U_NDEBUG_OPT_IS_SET=1
                    break
                }
            done

            if [ "$_U_NDEBUG_OPT_IS_SET" != 1 ] ; then
                PPFLAGS="$PPFLAGS -DNDEBUG"
            fi

            if [ -z "$ENABLE_LTO" ] || [ "$ENABLE_LTO" = 1 ] ; then
                LDFLAGS="$LDFLAGS -flto"
            fi

            case $ENABLE_STRIP in
                all)   LDFLAGS="$LDFLAGS -Wl,-s" ;;
                debug) LDFLAGS="$LDFLAGS -Wl,-S" ;;
            esac
    esac

    ##############################################

    for DEPENDENT_PACKAGE_NAME in $RECURSIVE_DEPENDENT_PACKAGE_NAMES
    do
        DEPENDENT_PACKAGE_NAME_UNDERSCORE=$(printf '%s\n' "$DEPENDENT_PACKAGE_NAME" | tr '@+-.' '_')

        DEPENDENT_PACKAGE_INSTALL_DIR="$NDKPKG_PACKAGE_INSTALLED_ROOT/$TARGET_PLATFORM_SPEC/$DEPENDENT_PACKAGE_NAME"
        DEPENDENT_PACKAGE_INCLUDE_DIR="$DEPENDENT_PACKAGE_INSTALL_DIR/include"
        DEPENDENT_PACKAGE_LIBRARY_DIR="$DEPENDENT_PACKAGE_INSTALL_DIR/lib"
        DEPENDENT_PACKAGE_PKGCONF_DIR="$DEPENDENT_PACKAGE_INSTALL_DIR/lib/pkgconfig"

        eval "${DEPENDENT_PACKAGE_NAME_UNDERSCORE}_INSTALL_DIR='$DEPENDENT_PACKAGE_INSTALL_DIR'"
        eval "${DEPENDENT_PACKAGE_NAME_UNDERSCORE}_INCLUDE_DIR='$DEPENDENT_PACKAGE_INCLUDE_DIR'"
        eval "${DEPENDENT_PACKAGE_NAME_UNDERSCORE}_LIBRARY_DIR='$DEPENDENT_PACKAGE_LIBRARY_DIR'"

        if [ -d "$DEPENDENT_PACKAGE_INCLUDE_DIR" ] ; then
            PPFLAGS="-I$DEPENDENT_PACKAGE_INCLUDE_DIR $PPFLAGS"
        fi

        if [ -d "$DEPENDENT_PACKAGE_LIBRARY_DIR" ] ; then
            LDFLAGS="-L$DEPENDENT_PACKAGE_LIBRARY_DIR -Wl,-rpath-link,$DEPENDENT_PACKAGE_LIBRARY_DIR $LDFLAGS"
        fi
    done

    PPFLAGS="-I$PACKAGE_INSTALLING_INC_DIR $PPFLAGS"
    LDFLAGS="-L$PACKAGE_INSTALLING_LIB_DIR $LDFLAGS"

    for DEPENDENT_PACKAGE_NAME in $PACKAGE_DEP_PKG
    do
        # https://android.googlesource.com/platform/bionic/+/master/docs/status.md

        case $DEPENDENT_PACKAGE_NAME in
            libexecinfo)
                if [ "$TARGET_PLATFORM_VERS" -lt 33 ] ; then
                    # https://android.googlesource.com/platform/bionic/+/master/libc/include/execinfo.h
                    # https://android.googlesource.com/platform/bionic/+/master/libc/bionic/execinfo.cpp
                    PPFLAGS="$PPFLAGS -include $libexecinfo_INCLUDE_DIR/execinfo.h"
                    LDFLAGS="$LDFLAGS -l:libexecinfo.a -lm"
                fi
                ;;
            libgetloadavg)
                if [ "$TARGET_PLATFORM_VERS" -lt 29 ] ; then
                    # https://android.googlesource.com/platform/bionic/+/master/libc/include/stdlib.h#157
                    # https://android.googlesource.com/platform/bionic/+/master/libc/bionic/getloadavg.cpp
                    # int getloadavg(double __averages[], int __n) __INTRODUCED_IN(29);
                    PPFLAGS="$PPFLAGS -include $libgetloadavg_INCLUDE_DIR/getloadavg.h"
                    LDFLAGS="$LDFLAGS -l:libgetloadavg.a"
                fi
                ;;
            libglob)
                # https://pubs.opengroup.org/onlinepubs/9699919799/functions/glob.html
                # https://android.googlesource.com/platform/bionic/+/master/libc/include/glob.h
                if [ "$TARGET_PLATFORM_VERS" -lt 28 ] ; then
                    LDFLAGS="$LDFLAGS -l:libglob.a"
                fi
                ;;
            liblanginfo)
                # https://pubs.opengroup.org/onlinepubs/9699919799/functions/nl_langinfo.html
                # https://android.googlesource.com/platform/bionic/+/master/libc/include/langinfo.h
                if [ "$TARGET_PLATFORM_VERS" -lt 26 ] ; then
                    LDFLAGS="$LDFLAGS -l:liblanginfo.a"
                fi
                ;;
            libmblen)
                # https://android.googlesource.com/platform/bionic/+/master/libc/include/stdlib.h#163
                # https://android.googlesource.com/platform/bionic/+/master/libc/bionic/mblen.cpp
                # int mblen(const char* __s, size_t __n) __INTRODUCED_IN_NO_GUARD_FOR_NDK(26);
                if [ "$TARGET_PLATFORM_VERS" -lt 26 ] ; then
                    PPFLAGS="$PPFLAGS -include $libmblen_INCLUDE_DIR/mblen.h"
                    LDFLAGS="$LDFLAGS -l:libmblen.a"
                fi
                ;;
            libgetdomainname)
                # https://android.googlesource.com/platform/bionic/+/master/libc/include/unistd.h#313
                # https://android.googlesource.com/platform/bionic/+/master/libc/bionic/getdomainname.cpp
                # int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
                if [ "$TARGET_PLATFORM_VERS" -lt 26 ] ; then
                    PPFLAGS="$PPFLAGS -include $libgetdomainname_INCLUDE_DIR/getdomainname.h"
                    LDFLAGS="$LDFLAGS -l:libgetdomainname.a"
                fi
                ;;
            libstrchrnul)
                # https://android.googlesource.com/platform/bionic/+/master/libc/include/string.h#68
                # char* strchrnul(char* __s, int __ch) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
                if [ "$TARGET_PLATFORM_VERS" -lt 24 ] ; then
                    PPFLAGS="$PPFLAGS -include $libstrchrnul_INCLUDE_DIR/strchrnul.h"
                    LDFLAGS="$LDFLAGS -l:libstrchrnul.a"
                fi
                ;;
            libgetdtablesize)
                # https://android.googlesource.com/platform/bionic/+/72dc1c22dc6a92dea925398c9e3880364ab29c1c/libc/bionic/getdtablesize.c
                PPFLAGS="$PPFLAGS -include $libgetdtablesize_INCLUDE_DIR/getdtablesize.h"
                LDFLAGS="$LDFLAGS -l:libgetdtablesize.a"
                ;;
        esac
    done

    export   CFLAGS="$CCFLAGS"
    export CXXFLAGS="$XXFLAGS"
    export CPPFLAGS="$PPFLAGS"
    export  LDFLAGS="$LDFLAGS"

    #########################################################################################

    # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
    export XDG_DATA_DIRS

    for DEPENDENT_PACKAGE_INSTALL_DIR in $RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS
    do
        # https://gi.readthedocs.io/en/latest/tools/g-ir-scanner.html#environment-variables
        if [ -d "$DEPENDENT_PACKAGE_INSTALL_DIR/share/gir-1.0" ] ; then
            if [ -z "$XDG_DATA_DIRS" ] ; then
                XDG_DATA_DIRS="$DEPENDENT_PACKAGE_INSTALL_DIR/share"
            else
                XDG_DATA_DIRS="$DEPENDENT_PACKAGE_INSTALL_DIR/share:$XDG_DATA_DIRS"
            fi
        fi

        # https://help.gnome.org/admin//system-admin-guide/2.32/mimetypes-database.html.en
        if [ -d "$DEPENDENT_PACKAGE_INSTALL_DIR/share/mime" ] ; then
            if [ -z "$XDG_DATA_DIRS" ] ; then
                XDG_DATA_DIRS="$DEPENDENT_PACKAGE_INSTALL_DIR/share"
            else
                XDG_DATA_DIRS="$DEPENDENT_PACKAGE_INSTALL_DIR/share:$XDG_DATA_DIRS"
            fi
        fi
    done

    #########################################################################################

    # https://www.gnu.org/software/automake/manual/html_node/Macro-Search-Path.html
    export ACLOCAL_PATH

    for DEPENDENT_PACKAGE_INSTALL_DIR in $RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS
    do
        DEPENDENT_PACKAGE_ACLOCAL_PATH="$DEPENDENT_PACKAGE_INSTALL_DIR/share/aclocal"

        if [ -d "$DEPENDENT_PACKAGE_ACLOCAL_PATH" ] ; then
            if [ -z "$ACLOCAL_PATH" ] ; then
                ACLOCAL_PATH="$DEPENDENT_PACKAGE_ACLOCAL_PATH"
            else
                ACLOCAL_PATH="$DEPENDENT_PACKAGE_ACLOCAL_PATH:$ACLOCAL_PATH"
            fi
        fi
    done

    #########################################################################################

    PATH="$PACKAGE_INSTALLING_BIN_DIR:$ANDROID_NDK_HOME:$PATH"

    #########################################################################################

    # override the default search directory (usually /usr/lib/pkgconfig:/usr/share/pkgconfig)
    # because we only want to use our own
    export PKG_CONFIG_LIBDIR="$PACKAGE_WORKING_DIR/lib/pkgconfig"
    export PKG_CONFIG_PATH="$PACKAGE_WORKING_DIR/lib/pkgconfig"

    for DEPENDENT_PACKAGE_INSTALL_DIR in $RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS
    do
        for d in lib share
        do
            DEPENDENT_PACKAGE_PKGCONF_DIR="$DEPENDENT_PACKAGE_INSTALL_DIR/$d/pkgconfig"

            if [ -d "$DEPENDENT_PACKAGE_PKGCONF_DIR" ] ; then
                PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$DEPENDENT_PACKAGE_PKGCONF_DIR"
            fi
        done
    done

    #########################################################################################

    for item in $PACKAGE_DEP_LIB
    do
        case $item in
            -l*);;
            *)  item="$(pkg-config --libs-only-l "$item")"
        esac

        ANDROID_NDK_COMPILER_ARGS="$ANDROID_NDK_COMPILER_ARGS $item"
    done

    #########################################################################################

    if [ "$PACKAGE_USE_BSYSTEM_CMAKE" = 1 ] ; then
        # https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html#manual:cmake-env-variables(7)

        unset CMAKE_PREFIX_PATH
        unset CMAKE_APPLE_SILICON_PROCESSOR
        unset CMAKE_BUILD_PARALLEL_LEVEL
        unset CMAKE_BUILD_TYPE
        unset CMAKE_CONFIGURATION_TYPES
        unset CMAKE_CONFIG_TYPE
        unset CMAKE_EXPORT_COMPILE_COMMANDS
        unset CMAKE_GENERATOR
        unset CMAKE_GENERATOR_INSTANCE
        unset CMAKE_GENERATOR_PLATFORM
        unset CMAKE_GENERATOR_TOOLSET
        unset CMAKE_INSTALL_MODE
        unset CMAKE_C_COMPILER_LAUNCHER
        unset CMAKE_C_LINKER_LAUNCHER
        unset CMAKE_CXX_COMPILER_LAUNCHER
        unset CMAKE_CXX_LINKER_LAUNCHER
        unset CMAKE_MSVCIDE_RUN_PATH
        unset CMAKE_NO_VERBOSE
        unset CMAKE_OSX_ARCHITECTURES
        unset CMAKE_TOOLCHAIN_FILE
        unset DESTDIR
        unset CTEST_INTERACTIVE_DEBUG_MODE
        unset CTEST_OUTPUT_ON_FAILURE
        unset CTEST_PARALLEL_LEVEL
        unset CTEST_PROGRESS_OUTPUT
        unset CTEST_USE_LAUNCHERS_DEFAULT
        unset DASHBOARD_TEST_FROM_CTEST

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_BUILD_PARALLEL_LEVEL.html
        export CMAKE_BUILD_PARALLEL_LEVEL="$BUILD_NJOBS"

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_GENERATOR.html
        if [ "$PACKAGE_USE_BSYSTEM_NINJA" = 1 ] ; then
            export CMAKE_GENERATOR='Ninja'
        else
            export CMAKE_GENERATOR='Unix Makefiles'
        fi

        # https://cmake.org/cmake/help/latest/envvar/CMAKE_EXPORT_COMPILE_COMMANDS.html
        if [ "$REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON" = 1 ] ; then
            export CMAKE_EXPORT_COMPILE_COMMANDS=ON
        else
            export CMAKE_EXPORT_COMPILE_COMMANDS=OFF
        fi

        case $PROFILE in
            debug)   CMAKE_BUILD_TYPE=Debug   ;;
            release) CMAKE_BUILD_TYPE=Release ;;
        esac

        if [ "$VERBOSE_CMAKE" = 1 ] ; then
            CMAKE_VERBOSE_MAKEFILE=ON
            CMAKE_COLOR_MAKEFILE=ON
            CMAKE_INSTALL_MESSAGE=ALWAYS
        else
            CMAKE_VERBOSE_MAKEFILE=OFF
            CMAKE_COLOR_MAKEFILE=OFF
            CMAKE_INSTALL_MESSAGE=NEVER
        fi

        # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_DEBUG_MODE.html
        if [ "$DEBUG_CMAKE" = 1 ] ; then
            CMAKE_FIND_DEBUG_MODE=ON
        else
            CMAKE_FIND_DEBUG_MODE=OFF
        fi

        # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_ROOT_PATH.html
        unset CMAKE_FIND_ROOT_PATH

        if [ -n "$PACKAGE_DEP_PKG" ] ; then
            CMAKE_FIND_ROOT_PATH="$(printf '%s\n' "$RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS" | tr ' ' ';')"
        fi
    fi

    #########################################################################################

    if [ "$PACKAGE_USE_BSYSTEM_CARGO" = 1 ] ; then
        # https://docs.rs/backtrace/latest/backtrace/
        export RUST_BACKTRACE=1

        # this environment variable is not defined by Rust, but it is widely used by third-party project.
        case $TARGET_PLATFORM_ARCH in
            armv7a)  export RUST_TARGET='armv7-linux-androideabi' ;;
            aarch64) export RUST_TARGET='aarch64-linux-android'   ;;
            i686)    export RUST_TARGET='i686-linux-android'      ;;
            x86_64)  export RUST_TARGET='x86_64-linux-android'    ;;
        esac

        RUST_TARGET_UPPERCASE_UNDERSCORE=$(printf '%s\n' "$RUST_TARGET" | tr a-z A-Z | tr - _)

        # https://doc.rust-lang.org/cargo/reference/config.html#environment-variables
        # https://doc.rust-lang.org/cargo/reference/environment-variables.html
        export "CARGO_TARGET_${RUST_TARGET_UPPERCASE_UNDERSCORE}_AR"="$AR"
        export "CARGO_TARGET_${RUST_TARGET_UPPERCASE_UNDERSCORE}_LINKER"="$CC"

        export CARGO_BUILD_JOBS="$BUILD_NJOBS"

        #########################################################################

        # https://doc.rust-lang.org/rustc/codegen-options/index.html#link-arg
        export RUSTFLAGS="-Clinker=$CC"

        for LDFLAG in $LDFLAGS
        do
            RUSTFLAGS="$RUSTFLAGS -Clink-arg=$LDFLAG"
        done

        #if [ "$TARGET_PLATFORM_ARCH" = x86_64 ] || [ "$TARGET_PLATFORM_ARCH" = i686 ] ; then
            LIBCLANG_RT_BUILTINS_FILEPATH="$("$CC" -print-libgcc-file-name)"
            RUSTFLAGS="$RUSTFLAGS -Clink-arg=$LIBCLANG_RT_BUILTINS_FILEPATH"
        #fi

        #########################################################################

        RUST_TARGET_FOR_BUILD="$(rustc -vV | sed -n '/host: /p' | cut -c7- | tr 'a-z-' 'A-Z_')"

        # https://doc.rust-lang.org/cargo/reference/config.html#environment-variables
        # https://doc.rust-lang.org/cargo/reference/environment-variables.html
        export "CARGO_TARGET_${RUST_TARGET_FOR_BUILD}_AR"="$AR_FOR_BUILD"
        export "CARGO_TARGET_${RUST_TARGET_FOR_BUILD}_LINKER"="$CC_FOR_BUILD"

        #########################################################################

        # https://docs.rs/openssl/latest/openssl/
        [ "$PACKAGE_DEP_UPP_LIBOPENSSL" = 1 ] && {
            eval export "${RUST_TARGET_FOR_BUILD}_OPENSSL_DIR='$NATIVE_PACKAGE_INSTALLED_ROOT/openssl'"
        }

        #########################################################################

        for DEPENDENT_PACKAGE_NAME in $RECURSIVE_DEPENDENT_PACKAGE_NAMES
        do
            case $DEPENDENT_PACKAGE_NAME in
                openssl@1.1)
                    # https://docs.rs/openssl/latest/openssl/
                    export OPENSSL_DIR="$openssl_1_1_INSTALL_DIR"

                    if [ "$PACKAGE_PKGTYPE" = exe ] ; then
                        # https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/main.rs
                        export OPENSSL_STATIC=1
                        export OPENSSL_NO_VENDOR=1
                    fi
                    ;;
                openssl-dev)
                    # https://docs.rs/openssl/latest/openssl/
                    export OPENSSL_DIR="$openssl_dev_INSTALL_DIR"

                    if [ "$PACKAGE_PKGTYPE" = exe ] ; then
                        # https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/main.rs
                        export OPENSSL_STATIC=1
                        export OPENSSL_NO_VENDOR=1
                    fi
                    ;;
                libssh2)
                    if [ "$PACKAGE_PKGTYPE" = exe ] ; then
                        # https://github.com/alexcrichton/ssh2-rs/blob/master/libssh2-sys/build.rs
                        export LIBSSH2_SYS_USE_PKG_CONFIG=1
                    fi
                    ;;
                libgit2)
                    if [ "$PACKAGE_PKGTYPE" = exe ] ; then
                        # https://github.com/rust-lang/git2-rs/blob/master/libgit2-sys/build.rs
                        export LIBGIT2_NO_VENDOR=1
                        export LIBGIT2_SYS_USE_PKG_CONFIG=1
                    fi
                    ;;
                libz|zlib)
                    if [ "$PACKAGE_PKGTYPE" = exe ] ; then
                        # https://github.com/rust-lang/libz-sys/blob/main/build.rs
                        export LIBZ_SYS_STATIC=1
                    fi
                    ;;
            esac
        done

        #########################################################################

        # https://libraries.io/cargo/cc
        # https://crates.io/crates/cc
        # https://docs.rs/cc/latest/cc/
        # https://github.com/alexcrichton/cc-rs
        export HOST_CC="$CC_FOR_BUILD"
        export HOST_CFLAGS="$CFLAGS_FOR_BUILD"

        export HOST_CXX="$CXX_FOR_BUILD"
        export HOST_CXXFLAGS="$CXXFLAGS_FOR_BUILD"

        export HOST_AR="$AR_FOR_BUILD"

        export TARGET_CC="$CC"
        export TARGET_CFLAGS="$CFLAGS $CPPFLAGS $LDFLAGS"

        export TARGET_CXX="$CXX"
        export TARGET_CXXFLAGS="$CXXFLAGS $CPPFLAGS $LDFLAGS"

        export TARGET_AR="$AR"

        #########################################################################

        # https://libraries.io/cargo/pkg-config
        # https://crates.io/crates/pkg-config
        # https://docs.rs/pkg-config/latest/pkg_config/
        # https://github.com/rust-lang/pkg-config-rs
        export TARGET_PKG_CONFIG_ALLOW_CROSS=1

        export HOST_PKG_CONFIG_PATH="$PKG_CONFIG_PATH_FOR_BUILD"
        export HOST_PKG_CONFIG_LIBDIR="$NDKPKG_CORE_DIR/lib"

        unset PKG_CONFIG_SYSROOT_DIR

        #########################################################################

        # https://libraries.io/cargo/cmake
        # https://crates.io/crates/cmake
        # https://docs.rs/cmake/latest/cmake/
        # https://github.com/alexcrichton/cmake-rs
        # this variable is not motioned in their document. you must read the source code of cmake-rs crate.
        export TARGET_CMAKE_TOOLCHAIN_FILE="$PACKAGE_WORKING_DIR/android.toolchain.cmake"

        cat > "$TARGET_CMAKE_TOOLCHAIN_FILE" <<EOF
set(ANDROID_ABI "${TARGET_PLATFORM_ABI}")
set(ANDROID_PLATFORM "android-${TARGET_PLATFORM_VERS}")
include(${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake)

set(CMAKE_C_COMPILER "$CC")
set(CMAKE_C_FLAGS "$CPPFLAGS $CFLAGS")

set(CMAKE_CXX_COMPILER "$CXX")
set(CMAKE_CXX_FLAGS "$CPPFLAGS $CXXFLAGS")

set(CMAKE_ASM_COMPILER "$CC")

set(CMAKE_SHARED_LINKER_FLAGS "$(printf '%s\n' "$LDFLAGS" | sed -e 's|--static||g' -e 's|-static||g')")
set(CMAKE_EXE_LINKER_FLAGS    "$LDFLAGS")

set(CMAKE_C_COMPILER_AR     "$AR")
set(CMAKE_C_COMPILER_RANLIB "$RANLIB")

set(CMAKE_CXX_COMPILER_AR     "$AR")
set(CMAKE_CXX_COMPILER_RANLIB "$RANLIB")

set(CMAKE_AR      "$AR")
set(CMAKE_RANLIB  "$RANLIB")

set(CMAKE_LINKER  "$LD")

set(CMAKE_NM      "$NM")
set(CMAKE_READELF "$READELF")

set(CMAKE_OBJCOPY "$OBJCOPY")
set(CMAKE_OBJDUMP "$OBJDUMP")

set(CMAKE_STRIP   "$STRIP")

set(CMAKE_ADDR2LINE "$ADDR2LINE")
EOF
    fi

    #########################################################################################

    if [ "$PACKAGE_USE_BSYSTEM_GO" = 1 ] ; then
        # https://pkg.go.dev/cmd/cgo
        export CGO_ENABLED=1
        export CGO_CFLAGS="$CFLAGS"
        export CGO_CXXFLAGS="$CXXFLAGS"
        export CGO_CPPFLAGS="$CPPFLAGS"
        export CGO_LDFLAGS="$LDFLAGS"

        # https://go.dev/blog/go116-module-changes
        export GO111MODULE='auto'

        if [ "$COUNTRY" = china ] ; then
            export GOPROXY='https://goproxy.cn'
        fi

        # https://golang.org/doc/install/source#environment
        export GOOS='android'

        case $TARGET_PLATFORM_ARCH in
            armv7a)  export GOARCH=arm   ;;
            aarch64) export GOARCH=arm64 ;;
            i686)    export GOARCH=386   ;;
            x86_64)  export GOARCH=amd64 ;;
        esac
    fi

    #########################################################################################

    # https://pubs.opengroup.org/onlinepubs/000095399/functions/rindex.html
    # https://pubs.opengroup.org/onlinepubs/000095399/functions/bcmp.html
    # https://linux.die.net/man/2/wait3
    # https://stackoverflow.com/questions/32826175/ftello-and-fseeko-android-build-errors
    # https://linux.die.net/man/3/ftello
    # int   fseeko(FILE* __fp, off_t __offset, int __whence) __RENAME(fseeko64) __INTRODUCED_IN(24);
    # off_t ftello(FILE* __fp) __RENAME(ftello64) __INTRODUCED_IN(24);

    cat > "$NDKPKG_COMMON_H_FILEPATH" <<EOF
#ifndef NDKPKG_COMMON_H
#define NDKPKG_COMMON_H

//#define rindex(a,b) strrchr((a),(b))

#define bcmp(b1,b2,len) memcmp((b1), (b2), (size_t)(len))

#define wait3(status,options,rusage) waitpid(-1,status,options)

#if __ANDROID_API__ < 24
    #define ftello(f) ftell(f)
    #define fseeko    fseek
#endif

#endif
EOF

    #########################################################################################

    # https://developer.android.com/ndk/guides/stable_apis#c_library
    # Note that on Android, unlike Linux, there are no separate libpthread or librt libraries.
    # That functionality is included directly in libc, which does not need to be explicitly linked against.
    printf '!<arch>\n' > "$PACKAGE_WORKING_DIR/lib/libpthread.a"
    printf '!<arch>\n' > "$PACKAGE_WORKING_DIR/lib/librt.a"

    if [ "$PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE" = 1 ] ; then
        printf '!<arch>\n' > "$PACKAGE_WORKING_DIR/lib/liblog.a"
    fi

    if [ "$ANDROID_NDK_VERSION_MAJOR" -ge 23 ] ; then
        # https://github.com/rust-windowing/android-ndk-rs/issues/149
        if [ "$TARGET_PLATFORM_ARCH" = 'x86_64' ] ; then
            LIBCLANG_RT_BUILTINS_FILEPATH="$("$CC" -print-libgcc-file-name)"
        else
            LIBCLANG_RT_BUILTINS_FILEPATH=
        fi

        printf 'INPUT(%s -l:libunwind.a)\n' "$LIBCLANG_RT_BUILTINS_FILEPATH" > "$PACKAGE_WORKING_DIR/lib/libgcc.a"
    fi

    #########################################################################################

    [ -n "$RECURSIVE_DEPENDENT_PACKAGE_NAMES" ] && {
        if [ "$PACKAGE_PKGTYPE" = exe ] || [ "$PACKAGE_PKGTYPE" = pie ] ; then
            step "copy dependent libraries to linker first search dir"

            for DEPENDENT_PACKAGE_INSTALL_DIR in $RECURSIVE_DEPENDENT_PACKAGE_INSTALL_DIRS
            do
                DEPENDENT_PACKAGE_LIBRARY_DIR="$DEPENDENT_PACKAGE_INSTALL_DIR/lib"

                if [  -d "$DEPENDENT_PACKAGE_LIBRARY_DIR" ] ; then
                    find "$DEPENDENT_PACKAGE_LIBRARY_DIR" -maxdepth 1 -mindepth 1 -name 'lib*.a' -exec cp -L -v '{}' "$PACKAGE_WORKING_DIR/lib/" \;
                fi
            done
        fi
    }

    #########################################################################################

    [ "$ENABLE_CCACHE" = 1 ] && {
        step "setup ccache"

        run ln -sf "$CCACHE" "$PACKAGE_WORKING_DIR/bin/wrapper-target-cc"
        run ln -sf "$CCACHE" "$PACKAGE_WORKING_DIR/bin/wrapper-target-c++"

        ccache -s > "$PACKAGE_WORKING_DIR/ccache-s.txt"
    }

    #########################################################################################

    step "dopatch for target"

    [ -f "$PACKAGE_INSTALLING_FIX_DIR/index" ] && {
        cd "$PACKAGE_BSCRIPT_DIR"

        for LINE in $(cat "$PACKAGE_INSTALLING_FIX_DIR/index")
        do
            FILE="$(printf '%s\n' "$LINE" | cut -d '|' -f1)"
            OPTS="$(printf '%s\n' "$LINE" | cut -d '|' -f2)"
            [ -z "$OPTS" ] && OPTS='-p1'
            run "patch $OPTS < $PACKAGE_INSTALLING_FIX_DIR/$FILE"
        done
    }

    [ -n "$PACKAGE_DOPATCH" ] && {
        cd "$PACKAGE_BSCRIPT_DIR"

        eval "
dopatch() {
$PACKAGE_DOPATCH
}"
        dopatch
    }

    #########################################################################################

    cd "$PACKAGE_BSCRIPT_DIR"

    #########################################################################################

    # https://github.com/golang/go/issues/65568
    [ -f go.mod ] && gsed -i 's|^go 1.22$|go 1.22.0|' go.mod

    #########################################################################################

    case $PACKAGE_BSYSTEM_MASTER in
        autogen)
            if [ -f configure ] ; then
                CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP="$(stat --format=%Y configure)"

                if [ -z "$CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP" ] ; then
                    run NOCONFIGURE=yes ./autogen.sh
                elif [ "$CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP" -lt "$TIMESTAMP_UNIX" ] ; then
                    run NOCONFIGURE=yes ./autogen.sh
                fi
            else
                run NOCONFIGURE=yes ./autogen.sh
            fi
            ;;
        autotools)
            if [ -f configure ] ; then
                CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP="$(stat --format=%Y configure)"

                if [ -z "$CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP" ] ; then
                    run autoreconf -ivf
                elif [ "$CONFIGURE_FILE_LAST_MODIFIED_TIMESTAMP" -lt "$TIMESTAMP_UNIX" ] ; then
                    run autoreconf -ivf
                fi
            else
                run autoreconf -ivf
            fi
            ;;
    esac

    #########################################################################################

    [ -n "$PACKAGE_PREPARE" ] && {
        step "prepare for target"

        eval "
prepare() {
$PACKAGE_PREPARE
}"
        prepare
    }

    #########################################################################################

    step "install for target"

    if [ "$PACKAGE_BINBSTD" = 1 ] ; then
        run cd "$PACKAGE_BSCRIPT_DIR"
    else
        run cd "$PACKAGE_BCACHED_DIR"
    fi

    if [        -d "$PACKAGE_INSTALL_DIR" ] ; then
        run rm -rf "$PACKAGE_INSTALL_DIR"
    fi

    [ "$DUMP_ENV" = 1 ] && {
        run export -p
        echo
    }

    eval "
dobuild() {
$PACKAGE_DOBUILD
}"

    dobuild

    #########################################################################################

    [   -d "$PACKAGE_INSTALL_DIR" ] || abort 1 "nothing was installed."

    step "change to the installed directory"
    run cd "$PACKAGE_INSTALL_DIR"

    [ -z "$(ls)" ]                  && abort 1 "nothing was installed."

    #########################################################################################

    step "dotweak for target"

    __tweak_pc_files

    [ -n "$PACKAGE_DOTWEAK" ] && {
        eval "
dotweak() {
$PACKAGE_DOTWEAK
}"
        dotweak
    }

    #########################################################################################

    [ -d  "$PACKAGE_INSTALL_DIR/lib" ] && {
        # https://www.linuxfromscratch.org/blfs/view/stable-systemd/introduction/la-files.html
        # remove Libtool Archive (.la) files
        find "$PACKAGE_INSTALL_DIR/lib" -maxdepth 1 -mindepth 1 \( -type f -or -type l \) -name '*.la' -exec rm '{}' \;
    }

    #########################################################################################

    PACKAGE_METAINFO_DIR="$PACKAGE_INSTALL_DIR/.ndk-pkg"

    PACKAGE_MANIFEST_FILEPATH="$PACKAGE_METAINFO_DIR/MANIFEST.txt"
    PACKAGE_RECEIPT_FILEPATH="$PACKAGE_METAINFO_DIR/RECEIPT.yml"

    PACKAGE_DEPENDENT_SHARED_LIBS_DIR="$PACKAGE_METAINFO_DIR/dependencies/lib"

    install -d "$PACKAGE_METAINFO_DIR"

    #########################################################################################

    # executable that need to be set rpath : $ORIGIN/../lib
    unset PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1

    # executable that need to be set rpath : $ORIGIN/../.ndk-pkg/dependencies/lib
    unset PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2

    step "docheck for target"
    __check_elf_files

    #########################################################################################

    [ "$PACKAGE_USE_BSYSTEM_CARGO" = 1 ] && {
        rm -f "$PACKAGE_INSTALL_DIR/.crates.toml"
        rm -f "$PACKAGE_INSTALL_DIR/.crates2.json"
    }

    #########################################################################################

    for item in 'FAQ*' 'TODO*' 'NEWS*' 'THANKS*' 'README*' 'COPYING*' 'LICENSE*' 'AUTHORS*' 'CHANGES*' 'CHANGELOG*' 'CONTRIBUTORS*' 'CONTRIBUTING*'
    do
        find "$PACKAGE_INSTALLING_SRC_DIR" -mindepth 1 -maxdepth 1 \( -type f -or -type l \) -iname "$item" -exec cp -L {} "$PACKAGE_METAINFO_DIR/" \;
    done

    #########################################################################################

    [ -n "$PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1" ] && {
        step "set rpath for executables"

        PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1="$(printf '%s\n' $PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1 | sort | uniq)"

        for f in $PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1
        do
            DIRNAME="${f%/*}"
            RELATIVE_PATH="$(realpath -m --relative-to="$DIRNAME" lib)"
            run patchelf --set-rpath "\\\$ORIGIN/$RELATIVE_PATH" "$f"
        done
    }

    [ -n "$PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2" ] && {
        step "set rpath for executables"

        PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2="$(printf '%s\n' $PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2 | sort | uniq)"

        for f in $PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2
        do
            DIRNAME="${f%/*}"
            RELATIVE_PATH="$(realpath -m --relative-to="$DIRNAME" .ndk-pkg/dependencies/lib)"
            run patchelf --set-rpath "\\\$ORIGIN/$RELATIVE_PATH" "$f"
        done
    }

    #########################################################################################

    [ -n "$PACKAGE_DEP_PKG" ] && {
        step "install dependency graph files"

        run mv "$PACKAGE_WORKING_DIR/dependencies.*" "$PACKAGE_METAINFO_DIR/"

        step "install dependency formulas"

        install -d "$PACKAGE_METAINFO_DIR/dependencies"

        for DEPENDENT_PACKAGE_NAME in $RECURSIVE_DEPENDENT_PACKAGE_NAMES
        do
            cp "$SESSION_DIR/$DEPENDENT_PACKAGE_NAME.yml" "$PACKAGE_METAINFO_DIR/dependencies/"
        done
    }

    #########################################################################################

    for dir in "$PACKAGE_BCACHED_DIR" "$PACKAGE_BSCRIPT_DIR"
    do
        if [ -f "$dir/config.log" ] ; then
            mv  "$dir/config.log" "$PACKAGE_METAINFO_DIR/"
        fi
    done

    #########################################################################################

    for dir in "$PACKAGE_BCACHED_DIR" "$PACKAGE_BSCRIPT_DIR"
    do
        if [ -f "$dir/compile_commands.json" ] ; then
            mv  "$dir/compile_commands.json" "$PACKAGE_METAINFO_DIR/"
        fi
    done

    #########################################################################################

    mv "$TOOLCHAIN_CONFIG_NATIVE" "$PACKAGE_METAINFO_DIR/"
    mv "$TOOLCHAIN_CONFIG_TARGET" "$PACKAGE_METAINFO_DIR/"

    #########################################################################################

    [ -n "$PACKAGE_ONFINAL" ] && {
        step "onfinal"

        cd "$PACKAGE_INSTALL_DIR"

        eval "
onfinal() {
$PACKAGE_ONFINAL
}"
        onfinal
    }

    #########################################################################################

    cd "$PACKAGE_INSTALL_DIR"

    step "generate MANIFEST.txt"
    __generate_manifest_of_the_given_package "$1"

    step "generate RECEIPT.yml"
    __generate_receipt_of_the_given_package "$1"

    step "generate index"
    run ln -s -r -f -T "$PACKAGE_INSTALL_DIR" "$NDKPKG_PACKAGE_INSTALLED_ROOT/$PACKAGE_SPEC"

    #########################################################################################

    [ "$ENABLE_CCACHE" = 1 ] && {
        step "show ccache statistics summary"
        note "Before Build:"
        run  cat "$PACKAGE_WORKING_DIR/ccache-s.txt"
        note "After  Build:"
        run  ccache -s
    }

    [ "$REQUEST_TO_KEEP_SESSION_DIR" != 1 ] && {
        step "delete the working directory"
        run rm -rf "$PACKAGE_WORKING_DIR"
    }

    #########################################################################################

    step "show installed files in tree-like format"
    run tree --dirsfirst -a "$PACKAGE_INSTALL_DIR"

    #########################################################################################

    printf '\n%b\n' "${COLOR_PURPLE}✅️  ${COLOR_OFF}${COLOR_GREEN}${1} was successfully installed.${COLOR_OFF}${COLOR_PURPLE}${COLOR_OFF}"

    if [ -n "$PACKAGE_CAVEATS" ] ; then
        printf '\n%b\n' "${COLOR_YELLOW}⚠️  Caveats:\n\n$PACKAGE_CAVEATS${COLOR_OFF}" >&2
    fi
}

__check_elf_files() {
    cd "$PACKAGE_INSTALL_DIR"

    FILEPATHs="$(find -not -name . -type f)"

    export IFS='
'

    for FILEPATH in $FILEPATHs
    do
        [ -f "$FILEPATH" ] || continue

        FILE_HEADER_ACTUAL="$(xxd -u -p -l 20 "$FILEPATH")"

        # http://www.sco.com/developers/gabi/latest/ch4.eheader.html
        case $FILE_HEADER_ACTUAL in
            7F454C46*)
                ELF_TYPE="$(printf '%s\n' "$FILE_HEADER_ACTUAL" | cut -c33-34)"

                case $TARGET_PLATFORM_ARCH in
                    armv7a)  FILE_HEADER_EXPACT="7F454C46010101000000000000000000${ELF_TYPE}002800" ;;
                    aarch64) FILE_HEADER_EXPACT="7F454C46020101000000000000000000${ELF_TYPE}00B700" ;;
                    i686)    FILE_HEADER_EXPACT="7F454C46010101000000000000000000${ELF_TYPE}000300" ;;
                    x86_64)  FILE_HEADER_EXPACT="7F454C46020101000000000000000000${ELF_TYPE}003E00" ;;
                esac

                if [ "$FILE_HEADER_EXPACT" != "$FILE_HEADER_ACTUAL" ] ; then
                    abort 1 "ELF file header mismatch: $FILEPATH\n    expect : $FILE_HEADER_EXPACT\n    actual : $FILE_HEADER_ACTUAL"
                fi

                #####################################################################

                # 03 means it is a shared library or dynamically linked executable
                if [ "$ELF_TYPE" = '03' ] ; then
                    # patchelf would report a error if there is no '.interp' section in a ELF file
                    PT_INTERP="$(patchelf --print-interpreter "$FILEPATH" 2>/dev/null || true)"

                    if [ -n  "$PT_INTERP" ] ; then
                        if [ "$PT_INTERP" != "$ANDROID_DYNAMIC_LINKER_PATH" ] ; then
                            abort 1 "ELF file PT_INTERP mismatch: $FILEPATH\n    expect : $ANDROID_DYNAMIC_LINKER_PATH\n    actual : $PT_INTERP"
                        fi

                        # https://source.android.com/security/enhancements/enhancements50
                        # Android 5.0 and later, a dynamically linked executable must be a PIE(Position Independent Executable)
                        if ! "$READELF" -d "$FILEPATH" | grep FLAGS_1 | grep -q PIE ; then
                            abort 1 "invalid ELF file: $FILEPATH\n    Android 5.0 and later requires dynamically linked executable to support PIE (position-independent executables)."
                        fi

                        # A dynamically linked executable always have the .interp section.
                        # In general, a shared library would not have the .interp section, but that is not always the case, for example, libcap/lib/libpsx.so is not only a library but also a executable.
                        case "${FILEPATH##*/}" in
                            *.so)
                                IS_SHARED_LIBRAY=1 ;;
                            *.so.*)
                                IS_SHARED_LIBRAY=1 ;;
                            *)  IS_SHARED_LIBRAY=0 ;;
                        esac
                    else
                        IS_SHARED_LIBRAY=1
                    fi

                    #####################################################################

                    if [ "$IS_SHARED_LIBRAY" = 1 ] ; then
                        # http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#dynamic_section
                        DT_SONAME="$(patchelf --print-soname "$FILEPATH")"

                        # On Android, a so file must have the DT_SONAME
                        # https://github.com/android/ndk/issues/1865
                        # https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md
                        if [ -z "$DT_SONAME" ] ; then
                            abort 1 "invalid .so file: $FILEPATH\n    no DT_SONAME was set in .dynamic section"
                        fi

                        IS_EXECUTABLE=0
                    else
                        IS_EXECUTABLE=1
                    fi

                    #####################################################################

                    __check_DT_NEEDED "$FILEPATH" "$IS_EXECUTABLE"
                fi
        esac
    done

    unset IFS
}

# __check_DT_NEEDED <ELF-FILE-PATH> <IS-EXECUTABLE>
  __check_DT_NEEDED() {
    # a \n-separated list
    DT_NEEDED_LIST="$(patchelf --print-needed "$1")"

    for DT_NEEDED in $DT_NEEDED_LIST
    do
        case $DT_NEEDED in
            libc.so)
                ;;
            libm.so)
                ;;
            libdl.so)
                ;;
            libomp.so)
                ;;
            liblog.so)
                ;;
            libandroid.so)
                ;;
            libmediandk.so)
                ;;
            libcamera2ndk.so)
                ;;
            libjnigraphics.so)
                ;;
            libOpenSLES.so)
                ;;
            libOpenMAXAL.so)
                ;;
            libEGL.so)
                ;;
            libGLESv1_CM.so)
                ;;
            libGLESv2.so)
                ;;
            libGLESv3.so)
                ;;
            libstdc++.so)
                ;;
            libc++_shared.so)
                ;;
            libclang_rt.*.so)
                ;;
            lib*.so)
                DT_NEEDED_FILEPATH="$PACKAGE_INSTALL_DIR/lib/$DT_NEEDED"

                if [ -f "$DT_NEEDED_FILEPATH" ] ; then
                    if [ "$2" = 1 ] ; then
                        PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1="$PACKAGE_EXECUTABLES_NEED_SET_RPATH_S1 $1"
                    fi
                else
                    unset DT_NEEDED_FILEPATH

                    if [ -n "$RECURSIVE_DEPENDENT_PACKAGE_NAMES" ] ; then
                        RECURSIVE_DEPENDENT_PACKAGE_NAMES2="$(printf '%s\n' "$RECURSIVE_DEPENDENT_PACKAGE_NAMES" | tr ' ' '\n')"

                        for DEPENDENT_PACKAGE_NAME in $RECURSIVE_DEPENDENT_PACKAGE_NAMES2
                        do
                            DT_NEEDED_FILEPATH="$NDKPKG_PACKAGE_INSTALLED_ROOT/$TARGET_PLATFORM_SPEC/$DEPENDENT_PACKAGE_NAME/lib/$DT_NEEDED"

                            if [ -f "$DT_NEEDED_FILEPATH" ] ; then
                                if [ !      -d    "$PACKAGE_DEPENDENT_SHARED_LIBS_DIR" ] ; then
                                    install -d -v "$PACKAGE_DEPENDENT_SHARED_LIBS_DIR"
                                fi

                                if [ ! -f "$PACKAGE_DEPENDENT_SHARED_LIBS_DIR/$DT_NEEDED" ] ; then
                                    cp -L -v "$DT_NEEDED_FILEPATH" "$PACKAGE_DEPENDENT_SHARED_LIBS_DIR/"
                                fi

                                if [ "$2" = 1 ] ; then
                                    PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2="$PACKAGE_EXECUTABLES_NEED_SET_RPATH_S2 $1"
                                fi

                                break
                            else
                                unset DT_NEEDED_FILEPATH
                            fi
                        done
                    fi
                fi

                if [ -z "$DT_NEEDED_FILEPATH" ] ; then
                    abort 1 "NEEDED: $DT_NEEDED not found for ELF file: $1"
                else
                    __check_DT_NEEDED "$DT_NEEDED_FILEPATH" 0
                fi
                ;;
            *)  abort 1 "unexpected ELF file: $1\n    invalid DT_NEEDED: $DT_NEEDED"
        esac
    done
}

__tweak_pc_files() {
    unset PC_FILES

    for item in lib share
    do
        PC_FILES_LIVEDIR="$PACKAGE_INSTALL_DIR/$item/pkgconfig"

        if [ -d        "$PC_FILES_LIVEDIR" ] ; then
            fs="$(find "$PC_FILES_LIVEDIR" -type f -name '*.pc')"

            if [ -n "$fs" ] ; then
                PC_FILES="$PC_FILES $fs"
            fi
        fi
    done

    for pcfile in $PC_FILES
    do
        gsed -i "s|$PACKAGE_INSTALL_DIR|\${pcfiledir}/../..|g" "$pcfile"

        gsed -i "s|-I$NDKPKG_HOME[^' ]*||g"   "$pcfile"
        gsed -i "s|-L$NDKPKG_HOME[^' ]*||g"   "$pcfile"
        gsed -i "s|-L$SYSROOT[^' ]*||g"       "$pcfile"
        gsed -i "s|--sysroot=$SYSROOT||"      "$pcfile"
        gsed -i 's|-flto||g'                  "$pcfile"
        gsed -i 's|-lpthread||g'              "$pcfile"
        gsed -i 's|-Wl,--strip-debug||g'      "$pcfile"

        gsed -i "s|${NDKPKG_HOME}/.*/lib\(.*\)\.so|-l\1|g" "$pcfile"
        gsed -i "s|${NDKPKG_HOME}/.*/lib\(.*\)\.a|-l\1|g"  "$pcfile"

        if grep -q 'Libs.private:' "$pcfile" ; then
            LIBS_CONTENT=$(awk '/Libs:/{print}' "$pcfile")
            LIBS_PRIVATE_CONTENT=$(awk -F: '/Libs.private:/{print $2}' "$pcfile")
            gsed -i "s|$LIBS_CONTENT|$LIBS_CONTENT$LIBS_PRIVATE_CONTENT|" "$pcfile"
            gsed -i '/Libs.private/d' "$pcfile"
        fi

        if grep -q 'Requires.private:' "$pcfile" ; then
            if grep -q 'Requires:' "$pcfile" ; then
                REQUIRES_PRIVATE_CONTENT=$(sed -n '/Requires.private:/p' "$pcfile" | cut -c18-)
                gsed -i "/Requires:/s|\$|$REQUIRES_PRIVATE_CONTENT|" "$pcfile"
                gsed -i '/Requires.private:/d' "$pcfile"
            else
                gsed -i 's|Requires.private:|Requires:|' "$pcfile"
            fi
        fi
    done
}

install_incs() {
    while [ -n "$1" ]
    do
        unset X1
        unset X2
        X1=$(printf '%s\n' "$1" | cut -d: -f1)
        X2=$(printf '%s\n' "$1" | cut -d: -f2)

        if [ "$X1" = "$X2" ] ; then
            unset X2
        fi

        install -v -d         "$PACKAGE_INSTALL_DIR/include/$X2"
        install -v -m 644 $X1 "$PACKAGE_INSTALL_DIR/include/$X2"

        shift
    done
}

install_libs() {
    install -v -d "$PACKAGE_INSTALL_DIR/lib"
    for item in "$@"
    do
        case $item in
            *.a) install -v -m 644 "$item" "$PACKAGE_INSTALL_DIR/lib" ;;
            *)   install -v -m 755 "$item" "$PACKAGE_INSTALL_DIR/lib" ;;
        esac
    done
}

writepc() {
    install -v -d "$PACKAGE_INSTALL_DIR/lib/pkgconfig" &&
    cat >         "$PACKAGE_INSTALL_DIR/lib/pkgconfig/$1.pc"
}

install_pcfs() {
    install -v -d          "$PACKAGE_INSTALL_DIR/lib/pkgconfig" &&
    install -v -m 644 "$@" "$PACKAGE_INSTALL_DIR/lib/pkgconfig"
}

install_bins() {
    install -v -d          "$PACKAGE_INSTALL_DIR/bin" &&
    install -v -m 755 "$@" "$PACKAGE_INSTALL_DIR/bin"
}

install_etcs() {
    install -v -d          "$PACKAGE_INSTALL_DIR/etc" &&
    install -v -m 644 "$@" "$PACKAGE_INSTALL_DIR/etc"
}

install_mans() {
    for item in "$@"
    do
        unset NUMBER
        NUMBER=$(printf '%s\n' "$item" | cut -c ${#item}-${#item})
        case $NUMBER in
            [1-8]);;
            *)    abort 1 "$item: not a manpage."
        esac
        install -v -d             "$PACKAGE_INSTALL_DIR/share/man/man$NUMBER" &&
        install -v -m 644 "$item" "$PACKAGE_INSTALL_DIR/share/man/man$NUMBER"
    done
}

# install_completion <fish|bash|zsh> <COMMAND> <FILE-PATH>
  install_completion() {
    case $1 in
        bash)
            install -v -d          "$PACKAGE_INSTALL_DIR/share/bash/completions" &&
            install -v -m 644 "$3" "$PACKAGE_INSTALL_DIR/share/bash/completions/$2"
            ;;
        fish)
            install -v -d          "$PACKAGE_INSTALL_DIR/share/fish/vendor_completions.d" &&
            install -v -m 644 "$3" "$PACKAGE_INSTALL_DIR/share/fish/vendor_completions.d/$2.fish"
            ;;
        zsh)
            install -v -d          "$PACKAGE_INSTALL_DIR/share/zsh/site-functions" &&
            install -v -m 644 "$3" "$PACKAGE_INSTALL_DIR/share/zsh/site-functions/_$2"
            ;;
        *)  abort 1 "install_completion unsupported shell: $1"
    esac
}

__record_installed_files_of_the_given_package() {
    if [ -z "$2" ] ; then
        INSTALLED_FILES_FILEPATH="$PACKAGE_INSTALL_DIR/installed-files"
        printf '%s\n' "-- Installing: $INSTALLED_FILES_FILEPATH"

        touch "$INSTALLED_FILES_FILEPATH"
        return 0

        # TODO
        exec 7> "$INSTALLED_FILES_FILEPATH"

        __record_installed_files_of_the_given_package "$1" "$PACKAGE_INSTALL_DIR"

        exec 7>&-

        gsed -i "s|$PACKAGE_INSTALL_DIR/||" "$INSTALLED_FILES_FILEPATH"
    else
        for file in $(ls $2)
        do
            file="$2/$file"
            if [ -d "$file" ] ; then
                __record_installed_files_of_the_given_package "$1" "$file"
            else
                printf '%s %s\n' $(md5sum "$file") "$file" >&7
            fi
        done
    fi
}

gow() {
    if [ "$VERBOSE_GO" = 1 ] ; then
        run "go env | bat --language=bash --paging=never --style=plain"
    fi

    # https://pkg.go.dev/cmd/go
    # https://pkg.go.dev/cmd/link

    unset GO_BUILD_ARGS
    unset GO_BUILD_ARGV_V
    unset GO_BUILD_ARGV_X
    unset GO_BUILD_ARGV_O
    unset GO_BUILD_ARGV_MOD
    unset GO_BUILD_ARGV_TAGS
    unset GO_BUILD_ARGV_LDFLAGS

    unset GO_BUILD_ARGS_EXTRA

    while [ -n "$1" ]
    do
        case $1 in
            -v) shift ; GO_BUILD_ARGV_V='-v' ;;
            -x) shift ; GO_BUILD_ARGV_X='-x' ;;
            -o) shift ; GO_BUILD_ARGV_O="$1" ; shift ;;
            -X) shift
                if [ -z "$GO_BUILD_ARGV_LDFLAGS" ] ; then
                    GO_BUILD_ARGV_LDFLAGS="-X $1"
                else
                    GO_BUILD_ARGV_LDFLAGS="$GO_BUILD_ARGV_LDFLAGS -X $1"
                fi
                shift
                ;;
            -ldflags)
                shift
                if [ -z "$GO_BUILD_ARGV_LDFLAGS" ] ; then
                    GO_BUILD_ARGV_LDFLAGS="$1"
                else
                    GO_BUILD_ARGV_LDFLAGS="$1 $GO_BUILD_ARGV_LDFLAGS"
                fi
                shift
                ;;
            *)  GO_BUILD_ARGS_EXTRA="$GO_BUILD_ARGS_EXTRA $1" ; shift
        esac
    done

    GO_BUILD_ARGS='-trimpath'

    if [ -z "$GO_BUILD_ARGV_V" ] ; then
        if [ "$VERBOSE_GO" = 1 ] ; then
            GO_BUILD_ARGS="$GO_BUILD_ARGS -v"
        fi
    else
        GO_BUILD_ARGS="$GO_BUILD_ARGS -v"
    fi

    if [ -z "$GO_BUILD_ARGV_X" ] ; then
        if [ "$DEBUG_GO" = 1 ] ; then
            GO_BUILD_ARGS="$GO_BUILD_ARGS -x"
        fi
    else
        GO_BUILD_ARGS="$GO_BUILD_ARGS -x"
    fi

    if [ "$PROFILE" = release ] ; then
        GO_BUILD_ARGV_LDFLAGS="$GO_BUILD_ARGV_LDFLAGS -s -w"
    fi

    if [ "$NATIVE_PLATFORM_KIND" != darwin ] ; then
        if [ "$PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE" = 1 ] && [ "$CGO_ENABLED" -eq 1 ] ; then
            GO_BUILD_ARGV_LDFLAGS="$GO_BUILD_ARGV_LDFLAGS -linkmode external \"-extldflags=-static\""
        fi
    fi

    GO_BUILD_ARGS="$GO_BUILD_ARGS -ldflags '$GO_BUILD_ARGV_LDFLAGS'"

    if [ -z "$GO_BUILD_ARGV_O" ] ; then
        GO_BUILD_ARGS="$GO_BUILD_ARGS -o $PACKAGE_BCACHED_DIR/"
    else
        GO_BUILD_ARGS="$GO_BUILD_ARGS -o $PACKAGE_BCACHED_DIR/$GO_BUILD_ARGV_O"
    fi

    GO_BUILD_ARGS="$GO_BUILD_ARGS $GO_BUILD_ARGS_EXTRA"

    # shellcheck disable=SC2086
    run go build $GO_BUILD_ARGS

    for item in $(ls "$PACKAGE_BCACHED_DIR")
    do
        case $item in
            *.a)  run install_libs "$PACKAGE_BCACHED_DIR/$item" ;;
            *.so) run install_libs "$PACKAGE_BCACHED_DIR/$item" ;;
            *)    run install_bins "$PACKAGE_BCACHED_DIR/$item" ;;
        esac
    done
}

cargow() {
    run rustup target add "$RUST_TARGET"

    case $1 in
        build)
            # https://doc.rust-lang.org/cargo/commands/cargo-clean.html
            # https://doc.rust-lang.org/cargo/commands/cargo-build.html

            unset CARGO_BUILD_ARGS
            unset CARGO_BUILD_ARG_VV
            unset CARGO_BUILD_ARG_TARGET
            unset CARGO_BUILD_ARG_RELEASE

            for arg in $@
            do
                case $arg in
                    --vv)      CARGO_BUILD_ARG_VV=set      ;;
                    --target)  CARGO_BUILD_ARG_TARGET=set  ;;
                    --release) CARGO_BUILD_ARG_RELEASE=set ;;
                esac
            done

            CARGO_BUILD_ARGS="$@"

            if [ -z "$CARGO_BUILD_ARG_VV" ] ; then
                if [ "$DEBUG_CARGO" = 1 ] ; then
                    CARGO_BUILD_ARGS="$CARGO_BUILD_ARGS -vv"
                fi
            fi

            if [ -z "$CARGO_BUILD_ARG_RELEASE" ] ; then
                CARGO_BUILD_ARGS="$CARGO_BUILD_ARGS --release"
            fi

            if [ -z "$CARGO_BUILD_ARG_TARGET" ] ; then
                CARGO_BUILD_ARGS="$CARGO_BUILD_ARGS --target $RUST_TARGET"
            fi

            run cargo clean && run cargo $CARGO_BUILD_ARGS
            ;;
        install)
            # https://doc.rust-lang.org/cargo/commands/cargo-clean.html
            # https://doc.rust-lang.org/cargo/commands/cargo-install.html

            unset CARGO_INSTALL_ARGS
            unset CARGO_INSTALL_ARG_TARGET
            unset CARGO_INSTALL_ARG_PATH
            unset CARGO_INSTALL_ARG_ROOT
            unset CARGO_INSTALL_ARG_VV

            for arg in $@
            do
                case $arg in
                    --target) CARGO_INSTALL_ARG_TARGET=set ;;
                    --path)   CARGO_INSTALL_ARG_PATH=set   ;;
                    --root)   CARGO_INSTALL_ARG_ROOT=set   ;;
                    --vv)     CARGO_INSTALL_ARG_VV=set     ;;
                esac
            done

            CARGO_INSTALL_ARGS="$@"

            if [ -z "$CARGO_BUILD_ARG_VV" ] ; then
                if [ "$DEBUG_CARGO" = 1 ] ; then
                    CARGO_INSTALL_ARGS="$CARGO_INSTALL_ARGS -vv"
                fi
            fi

            if [ -z "$CARGO_INSTALL_ARG_TARGET" ] ; then
                CARGO_INSTALL_ARGS="$CARGO_INSTALL_ARGS --target $RUST_TARGET"
            fi

            if [ -z "$CARGO_INSTALL_ARG_PATH" ] ; then
                CARGO_INSTALL_ARGS="$CARGO_INSTALL_ARGS --path $PACKAGE_BSCRIPT_DIR"
            fi

            if [ -z "$CARGO_INSTALL_ARG_ROOT" ] ; then
                CARGO_INSTALL_ARGS="$CARGO_INSTALL_ARGS --root=$PACKAGE_INSTALL_DIR"
            fi

            run cargo clean && run cargo $CARGO_INSTALL_ARGS
            ;;
        cbuild|cinstall)
            unset CARGO_CINSTALL_ARGS
            unset CARGO_CINSTALL_ARG_Q
            unset CARGO_CINSTALL_ARG_V
            unset CARGO_CINSTALL_ARG_VV
            unset CARGO_CINSTALL_ARG_DEBUG
            unset CARGO_CINSTALL_ARG_RELEASE
            unset CARGO_CINSTALL_ARG_TARGET
            unset CARGO_CINSTALL_ARG_PREFIX

            for arg in $@
            do
                case $arg in
                    -q|--quiet)   CARGO_CINSTALL_ARG_Q=set       ;;
                    -v|--verbose) CARGO_CINSTALL_ARG_V=set       ;;
                    -vv)          CARGO_CINSTALL_ARG_VV=set      ;;
                    --debug)      CARGO_CINSTALL_ARG_DEBUG=set   ;;
                    --release)    CARGO_CINSTALL_ARG_RELEASE=set ;;
                    --target)     CARGO_CINSTALL_ARG_TARGET=set  ;;
                    --prefix)     CARGO_CINSTALL_ARG_PREFIX=set  ;;
                esac
            done

            CARGO_CINSTALL_ARGS="$@"

            if [ -z "$CARGO_CINSTALL_ARG_Q" ] && [ -z "$CARGO_CINSTALL_ARG_V" ] && [ -z "$CARGO_CINSTALL_ARG_VV" ] ; then
                if [ "$DEBUG_CARGO" = 1 ] ; then
                    CARGO_CINSTALL_ARGS="$CARGO_CINSTALL_ARGS -vv"
                fi
            fi

            if [ -z "$CARGO_CINSTALL_ARG_DEBUG" ] && [ -z "$CARGO_CINSTALL_ARG_RELEASE" ] ; then
                CARGO_CINSTALL_ARGS="$CARGO_CINSTALL_ARGS --release"
            fi

            if [ -z "$CARGO_CINSTALL_ARG_TARGET" ] ; then
                CARGO_CINSTALL_ARGS="$CARGO_CINSTALL_ARGS --target $RUST_TARGET"
            fi

            if [ -z "$CARGO_CINSTALL_ARG_PREFIX" ] ; then
                CARGO_CINSTALL_ARGS="$CARGO_CINSTALL_ARGS --prefix $PACKAGE_INSTALL_DIR"
            fi

            run cargo $CARGO_CINSTALL_ARGS
            ;;
        *) cargo $@
    esac
}

# }}}
##############################################################################
# {{{ waf

waf() {
    run python3 ./waf "$@"
}

# }}}
##############################################################################
# {{{ configure

configure() {
    unset CONFIGURE_ONLY

    if [ "$1" = only ] ; then
        CONFIGURE_ONLY=1
        shift
    fi

    if [ "$BUILD_FOR_NATIVE" = 1 ] ; then
        if run "$PACKAGE_BSCRIPT_DIR"/configure \
            --prefix="$PACKAGE_INSTALL_DIR" \
            $@ ; then
            echo
        else
            if [ -f "$PACKAGE_BCACHED_DIR/config.log" ] ; then
                run cat "$PACKAGE_BCACHED_DIR/config.log"
            elif [ -f "$PACKAGE_BSCRIPT_DIR/config.log" ] ; then
                run cat "$PACKAGE_BSCRIPT_DIR/config.log"
            fi
            return 1
        fi
    else
        # https://www.gnu.org/software/autoconf/manual/autoconf-2.71/html_node/Generic-Functions.html

        export ac_cv_search_log=-lm
        export ac_cv_search_ceil=-lm

        export ac_cv_lib_m_sqrt=yes

        export ac_cv_func_pow=yes
        export ac_cv_func_ffsl=yes
        export ac_cv_func_free=yes
        export ac_cv_func_calloc=yes
        export ac_cv_func_malloc=yes
        export ac_cv_func_realloc=yes
        export ac_cv_func_memset=yes
        export ac_cv_func_strchr=yes
        export ac_cv_func_strstr=yes
        export ac_cv_func_stpcpy=yes
        export ac_cv_func_strcpy=yes
        export ac_cv_func_strtol=yes
        export ac_cv_func_strdup=yes
        export ac_cv_func_strndup=yes
        export ac_cv_func_wcslen=yes
        export ac_cv_func_isblank=yes
        export ac_cv_func_strerror=yes
        export ac_cv_func_snprintf=yes
        export ac_cv_func_faccessat=yes
        export ac_cv_func_sigsetmask=no
        export ac_cv_func_strcasecmp=yes
        export ac_cv_func_vsnprintf=yes

        export ac_cv_func_malloc_0_nonnull=yes
        export ac_cv_func_calloc_0_nonnull=yes
        export ac_cv_func_realloc_0_nonnull=yes

        # https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md#is-32_bit-on-lp32-y2038
        if [ "$TARGET_PLATFORM_NBIT" -eq 32 ] ; then
            export ac_year2038_required=no
        fi

        # string.h  void* _Nonnull memset_explicit(void* _Nonnull __dst, int __ch, size_t __n) __INTRODUCED_IN(34);
        # stdio_ext.h  size_t __freadahead(FILE* _Nonnull __fp) __INTRODUCED_IN(34);
        if [ "$TARGET_PLATFORM_VERS" -ge 34 ] ; then
            export ac_cv_func_memset_explicit=yes
            export ac_cv_func___freadahead=yes
        else
            export ac_cv_func_memset_explicit=no
            export ac_cv_func___freadahead=no
        fi

        # sys/stat.h int statx(int __dir_fd, const char* _Nonnull __path, int __flags, unsigned __mask, struct statx* _Nonnull __buf) __INTRODUCED_IN(30);
        if [ "$TARGET_PLATFORM_VERS" -ge 30 ] ; then
            export ac_cv_func_statx=yes
        else
            export ac_cv_func_statx=no
        fi

        # malloc.h  void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
        if [ "$TARGET_PLATFORM_VERS" -ge 29 ] ; then
            export ac_cv_func_reallocarray=yes
        else
            export ac_cv_func_reallocarray=no
        fi

        # unistd.h     int syncfs(int __fd) __INTRODUCED_IN(28);
        # sys/random.h ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN(28);
        # stdio_ext.h  void __fseterr(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
        # stdio_ext.h  int __freading(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
        # stdio_ext.h  int __fwriting(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
        # stdio.h      size_t fwrite_unlocked(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
        # extern       void* _Nonnull (*volatile _Nonnull __malloc_hook)(size_t __byte_count, const void* _Nonnull __caller) __INTRODUCED_IN(28);
        # spawn.h      int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
        if [ "$TARGET_PLATFORM_VERS" -ge 28 ] ; then
            export ac_cv_func_syncfs=yes
            export ac_cv_func_getrandom=yes
            export ac_cv_func___fseterr=yes
            export ac_cv_func___freading=yes
            export ac_cv_func___fwriting=yes
            export ac_cv_func___malloc_hook=yes
            export ac_cv_func_fwrite_unlocked=yes
            export ac_cv_func_posix_spawnp=yes
            export ac_cv_func_posix_spawn_file_actions_init=yes
            export ac_cv_func_posix_spawn_file_actions_addclose=yes
            export ac_cv_func_posix_spawn_file_actions_adddup2=yes
            export ac_cv_func_posix_spawn_file_actions_destroy=yes
        else
            export ac_cv_func_syncfs=no
            export ac_cv_func_getrandom=no
            export ac_cv_func___fseterr=no
            export ac_cv_func___freading=no
            export ac_cv_func___fwriting=no
            export ac_cv_func___malloc_hook=no
            export ac_cv_func_fwrite_unlocked=no
            export ac_cv_func_posix_spawnp=no
            export ac_cv_func_posix_spawn_file_actions_init=no
            export ac_cv_func_posix_spawn_file_actions_addclose=no
            export ac_cv_func_posix_spawn_file_actions_adddup2=no
            export ac_cv_func_posix_spawn_file_actions_destroy=no
        fi

        # stdio.h     char* _Nonnull ctermid(char* _Nullable __buf) __INTRODUCED_IN(26);
        # sys/time.h  int futimesat(int __dir_fd, const char* __BIONIC_COMPLICATED_NULLNESS __path, const struct timeval __times[_Nullable 2]) __INTRODUCED_IN(26);
        # sys/time.h  int lutimes(const char* _Nonnull __path, const struct timeval __times[_Nullable 2]) __INTRODUCED_IN(26);
        # langinfo.h  char* _Nonnull nl_langinfo(nl_item __item) __INTRODUCED_IN(26);
        # pwd.h  struct passwd* getpwent(void) __INTRODUCED_IN(26);
        if [ "$TARGET_PLATFORM_VERS" -ge 26 ] ; then
            export ac_cv_func_futimesat=yes
            export ac_cv_func_futimes=yes
            export ac_cv_func_lutimes=yes
            export ac_cv_func_ctermid=yes
            export ac_cv_func_setpwent=yes
            export ac_cv_func_getpwent=yes
            export ac_cv_func_endpwent=yes
            export ac_cv_func_nl_langinfo=yes
        else
            export ac_cv_func_futimesat=no
            export ac_cv_func_futimes=no
            export ac_cv_func_lutimes=no
            export ac_cv_func_ctermid=no
            export ac_cv_func_setpwent=no
            export ac_cv_func_getpwent=no
            export ac_cv_func_endpwent=no
            export ac_cv_func_nl_langinfo=no
        fi

        # grp.h  int getgrnam_r(const char* _Nonnull __name, struct group* __BIONIC_COMPLICATED_NULLNESS __group, char* _Nonnull __buf, size_t __n, struct group* _Nullable *_Nonnull __result) __INTRODUCED_IN(24);
        # grp.h  int getgrgid_r(gid_t __gid, struct group* __group, char* __buf, size_t __n, struct group** __result) __INTRODUCED_IN(24);
        if [ "$TARGET_PLATFORM_VERS" -ge 24 ] ; then
            export ac_cv_func_getgrnam_r=yes
            export ac_cv_func_getgrgid_r=yes
        else
            export ac_cv_func_getgrnam_r=no
            export ac_cv_func_getgrgid_r=no
        fi

        # stdio_ext.h  int __fsetlocking(FILE* _Nonnull __fp, int __type) __INTRODUCED_IN(23);
        # string.h     char* _Nonnull strerror_l(int __errno_value, locale_t _Nonnull __l) __INTRODUCED_IN(23);
        # stdlib.h     int mkostemp(char* _Nonnull __template, int __flags) __INTRODUCED_IN(23);
        # stdio.h      FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
        if [ "$TARGET_PLATFORM_VERS" -ge 23 ] ; then
            export ac_cv_func_mempcpy=yes
            export ac_cv_func_wmempcpy=yes
            export ac_cv_func_mkostemp=yes
            export ac_cv_func_fmemopen=yes
            export ac_cv_func_strerror_l=yes
            export ac_cv_func___fsetlocking=yes
        else
            export ac_cv_func_mempcpy=no
            export ac_cv_func_wmempcpy=no
            export ac_cv_func_mkostemp=no
            export ac_cv_func_fmemopen=no
            export ac_cv_func_strerror_l=no
            export ac_cv_func___fsetlocking=no
        fi

        CONFIGURE_ARG_ENABLE_NLS=0
        CONFIGURE_ARG_ENABLE_RPATH=0
        CONFIGURE_ARG_ENABLE_LARGEFILE=1

        CONFIGURE_ARG_ENABLE_DEBUG=
        CONFIGURE_ARG_ENABLE_STATIC=
        CONFIGURE_ARG_ENABLE_SHARED=

        for arg in "$@"
        do
            case $arg in
                --enable-nls)      CONFIGURE_ARG_ENABLE_NLS=1 ;;
                --enable-nls=yes)  CONFIGURE_ARG_ENABLE_NLS=1 ;;
                --enable-nls=no)   CONFIGURE_ARG_ENABLE_NLS=0 ;;
                --disable-nls)     CONFIGURE_ARG_ENABLE_NLS=0 ;;

                --enable-rpath)     CONFIGURE_ARG_ENABLE_RPATH=1 ;;
                --enable-rpath=yes) CONFIGURE_ARG_ENABLE_RPATH=1 ;;
                --enable-rpath=no)  CONFIGURE_ARG_ENABLE_RPATH=0 ;;
                --disable-rpath)    CONFIGURE_ARG_ENABLE_RPATH=0 ;;

                --enable-largefile)     CONFIGURE_ARG_ENABLE_LARGEFILE=1 ;;
                --enable-largefile=yes) CONFIGURE_ARG_ENABLE_LARGEFILE=1 ;;
                --enable-largefile=no)  CONFIGURE_ARG_ENABLE_LARGEFILE=0 ;;
                --disable-largefile)    CONFIGURE_ARG_ENABLE_LARGEFILE=0 ;;

                --enable-debug)     CONFIGURE_ARG_ENABLE_DEBUG=1 ;;
                --enable-debug=yes) CONFIGURE_ARG_ENABLE_DEBUG=1 ;;
                --enable-debug=no)  CONFIGURE_ARG_ENABLE_DEBUG=0 ;;
                --disable-debug)    CONFIGURE_ARG_ENABLE_DEBUG=0 ;;

                --enable-static)     CONFIGURE_ARG_ENABLE_STATIC=1 ;;
                --enable-static=yes) CONFIGURE_ARG_ENABLE_STATIC=1 ;;
                --enable-static=no)  CONFIGURE_ARG_ENABLE_STATIC=0 ;;
                --disable-static)    CONFIGURE_ARG_ENABLE_STATIC=0 ;;

                --enable-shared)     CONFIGURE_ARG_ENABLE_SHARED=1 ;;
                --enable-shared=yes) CONFIGURE_ARG_ENABLE_SHARED=1 ;;
                --enable-shared=no)  CONFIGURE_ARG_ENABLE_SHARED=0 ;;
                --disable-shared)    CONFIGURE_ARG_ENABLE_SHARED=0 ;;
            esac
        done

        CONFIGURE_ARGS="--host='$TARGET_TRIPLE' --prefix='$PACKAGE_INSTALL_DIR' --disable-option-checking"

        if [ "$CONFIGURE_ARG_ENABLE_NLS" = 1 ] ; then
            CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-nls"
        else
            CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-nls"
        fi

        if [ "$CONFIGURE_ARG_ENABLE_RPATH" = 1 ] ; then
            CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-rpath"
        else
            CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-rpath"
        fi

        if [ "$CONFIGURE_ARG_ENABLE_LARGEFILE" = 1 ] ; then
            CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-largefile"
        else
            CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-largefile"
        fi

        if [ -z "$CONFIGURE_ARG_ENABLE_DEBUG" ] ; then
            case $PROFILE in
                debug)   CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-debug"  ;;
                release) CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-debug" ;;
            esac
        fi

        if [ -z "$CONFIGURE_ARG_ENABLE_STATIC" ] ; then
            CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-static"
        fi

        if [ -z "$CONFIGURE_ARG_ENABLE_SHARED" ] ; then
            if [ "$PACKAGE_PKGTYPE" = exe ] || [ "$PACKAGE_PKGTYPE" = pie ] ; then
                CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-shared"
            else
                CONFIGURE_ARGS="$CONFIGURE_ARGS --enable-shared"
            fi
        fi

        # https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md#is-32_bit-on-lp32-y2038
        if [ "$TARGET_PLATFORM_NBIT" = 32 ] ; then
            CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-year2038"
        fi

        CONFIGURE_ENVS="$CONFIGURE_ENVS --with-pic
            CC='$CC'
            CFLAGS='$CFLAGS'
            CXX='$CXX'
            CXXFLAGS='$CXXFLAGS'
            CPP='$CPP'
            CPPFLAGS='$CPPFLAGS'
            LDFLAGS='$LDFLAGS'
            AR='$AR'
            RANLIB='$RANLIB'
            PKG_CONFIG='$PKG_CONFIG'
            PKG_CONFIG_PATH='$PKG_CONFIG_PATH'
            PKG_CONFIG_LIBDIR='$PKG_CONFIG_LIBDIR'
            CC_FOR_BUILD='$CC_FOR_BUILD'"

        CONFIGURE="$PACKAGE_BSCRIPT_DIR/configure"

        gsed -i 's/cross_compiling=no/cross_compiling=yes/g' "$CONFIGURE"

        if run $CONFIGURE $CONFIGURE_ARGS $@ $CONFIGURE_ENVS ; then
            echo
        else
            # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables
            if [ "$GITHUB_ACTIONS" = true ] ; then
                if [ -f "$PACKAGE_BCACHED_DIR/config.log" ] ; then
                    run cat "$PACKAGE_BCACHED_DIR/config.log"
                elif [ -f "$PACKAGE_BSCRIPT_DIR/config.log" ] ; then
                    run cat "$PACKAGE_BSCRIPT_DIR/config.log"
                fi
            fi
            return 1
        fi
    fi

    if [ "$VERBOSE_GMAKE" = 1 ] ; then
        for Makefile in $(find "$PACKAGE_BSCRIPT_DIR" -name Makefile)
        do
            gsed -i 's|\t@|\t|g'     "$Makefile"
            gsed -i 's|@echo|echo|g' "$Makefile"
        done
        unset Makefile
    fi

    if [ "$CONFIGURE_ONLY" != 1 ] ; then
        gmakew clean
        gmakew
        gmakew install
    fi
}

# gmake wrapper
gmakew() {
    unset GMAKE_OPTIONS
    unset GMAKE_OPTION_SET_C
    unset GMAKE_OPTION_SET_w
    unset GMAKE_OPTION_SET_j

    for option in $@
    do
        case $option in
            -C)           GMAKE_OPTION_SET_C=1 ;;
            -w)           GMAKE_OPTION_SET_w=1 ;;
            -j)           GMAKE_OPTION_SET_j=1 ;;
            -j[1-9])      GMAKE_OPTION_SET_j=1 ;;
            -j[1-9][0-9]) GMAKE_OPTION_SET_j=1 ;;
        esac
    done

    if [ "$GMAKE_OPTION_SET_w" != 1 ] ; then
        GMAKE_OPTIONS="$GMAKE_OPTIONS -w"
    fi

    if [ "$GMAKE_OPTION_SET_C" != 1 ] ; then
        if [ "$PACKAGE_BINBSTD" != 1 ] ; then
            GMAKE_OPTIONS="$GMAKE_OPTIONS -C $PACKAGE_BCACHED_DIR"
        fi
    fi

    if [ "$GMAKE_OPTION_SET_j" != 1 ] ; then
        GMAKE_OPTIONS="$GMAKE_OPTIONS -j$BUILD_NJOBS"
    fi

    if [ "$VERBOSE_GMAKE" = 1 ] ; then
        GMAKE_OPTIONS="$GMAKE_OPTIONS V=1"
    fi

    if [ "$DEBUG_GMAKE" = 1 ] ; then
        GMAKE_OPTIONS="$GMAKE_OPTIONS --debug"
    fi

    if [ "$REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON" = 1 ] && [ "$BEAR_ENABLED" = 1 ] ; then
        run bear -- $GMAKE $GMAKE_OPTIONS $*
    else
        run         $GMAKE $GMAKE_OPTIONS $*
    fi
}

# cmakew [2] [--targets=<comma-separated list>] [--components=<comma-separated list>] [CMAKE-OPTIONS]
cmakew() {
    unset CMAKE_EXTRA_ARGS
    unset CMAKE_BUILD_TARGETS
    unset CMAKE_INSTALL_COMPONENTS
    unset CMAKE_BUILD_STATIC_SHARED_LIBRARY_SEPARATEDLY

    if [ "$1" = 2 ] ; then
        CMAKE_BUILD_STATIC_SHARED_LIBRARY_SEPARATEDLY=1
        shift
    fi

    while [ -n "$1" ]
    do
        case $1 in
            -S) shift; PACKAGE_BSCRIPT_DIR="$1" ;;
            -B) shift; PACKAGE_BCACHED_DIR="$1" ;;
            --targets=*)
                TARGETS="${1#*=}"

                export IFS=','

                for item in $TARGETS
                do
                    CMAKE_BUILD_TARGETS="$CMAKE_BUILD_TARGETS $item"
                done

                unset IFS
                ;;
            --components=*)
                COMPONENTS="${1#*=}"

                export IFS=','

                for item in $COMPONENTS
                do
                    CMAKE_INSTALL_COMPONENTS="$CMAKE_INSTALL_COMPONENTS $item"
                done

                unset IFS
                ;;
            *)  CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS $1"
        esac
        shift
    done

    if [ "$CMAKE_BUILD_STATIC_SHARED_LIBRARY_SEPARATEDLY" = 1 ] ; then
        cmakew_internal $CMAKE_EXTRA_ARGS -DBUILD_SHARED_LIBS=OFF
        cmakew_internal $CMAKE_EXTRA_ARGS -DBUILD_SHARED_LIBS=ON
    else
        cmakew_internal $CMAKE_EXTRA_ARGS
    fi
}

# https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling
# https://cmake.org/cmake/help/latest/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html
# https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_ROOT_PATH.html
# https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html
# https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html
# https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
# https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html
# https://cmake.org/cmake/help/latest/command/enable_testing.html?highlight=build_testing
# https://developer.android.com/ndk/guides/cmake
# run in a subshell
cmakew_internal() {
    if [ "$BUILD_FOR_NATIVE" = 1 ] ; then
        CMAKE_CONFIG_OPTIONS="-Wno-dev -DCMAKE_EXPORT_COMPILE_COMMANDS=$CMAKE_EXPORT_COMPILE_COMMANDS -DBUILD_TESTING=OFF"

        # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_DEBUG_MODE.html
        if [ "$DEBUG_CMAKE" = 1 ] ; then
            CMAKE_CONFIG_OPTIONS="$CMAKE_CONFIG_OPTIONS -DCMAKE_FIND_DEBUG_MODE=TRUE"
        fi

        CMAKE_CONFIG_OPTIONS="$CMAKE_CONFIG_OPTIONS -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX='$PACKAGE_INSTALL_DIR' -S $PACKAGE_BSCRIPT_DIR -B $PACKAGE_BCACHED_DIR"

        run $CMAKE $CMAKE_CONFIG_OPTIONS $@ &&
        run $CMAKE --build   "$PACKAGE_BCACHED_DIR" -- -j$BUILD_NJOBS &&
        run $CMAKE --install "$PACKAGE_BCACHED_DIR"
    else
        unset CMAKE_PROJECT_INCLUDE

        if [ "$PACKAGE_PKGTYPE" = exe ] || [ "$PACKAGE_PKGTYPE" = pie ] ; then
            # https://cmake.org/cmake/help/latest/variable/CMAKE_PROJECT_INCLUDE.html
            CMAKE_PROJECT_INCLUDE="$PACKAGE_WORKING_DIR/project-after.cmake"

            # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_LIBRARY_SUFFIXES.html
            if [ "$PACKAGE_CREATE_FULLY_STATICALLY_LINKED_EXECUTABLE" = 1 ] ; then
                printf 'set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")\n'       > "$CMAKE_PROJECT_INCLUDE"
            else
                printf 'set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".so")\n' > "$CMAKE_PROJECT_INCLUDE"
            fi

            if [ "$VERBOSE_CMAKE" = 1 ] ; then
                run cat "$CMAKE_PROJECT_INCLUDE"
            fi
        fi

        case $PROFILE in
            debug)   CMAKE_BUILD_TYPE=Debug   ;;
            release) CMAKE_BUILD_TYPE=Release ;;
        esac

        if [ "$VERBOSE_CMAKE" = 1 ] ; then
            CMAKE_VERBOSE_MAKEFILE=ON
            CMAKE_COLOR_MAKEFILE=ON
        else
            CMAKE_VERBOSE_MAKEFILE=OFF
            CMAKE_COLOR_MAKEFILE=OFF
        fi

        # https://cmake.org/cmake/help/latest/variable/CMAKE_FIND_DEBUG_MODE.html
        if [ "$DEBUG_CMAKE" = 1 ] ; then
            CMAKE_FIND_DEBUG_MODE=ON
        else
            CMAKE_FIND_DEBUG_MODE=OFF
        fi

        case $TARGET_PLATFORM_ARCH in
            armv7a)  CMAKE_SYSTEM_PROCESSOR=armv7-a ;;
            aarch64) CMAKE_SYSTEM_PROCESSOR=aarch64 ;;
            i686)    CMAKE_SYSTEM_PROCESSOR=i686    ;;
            x86_64)  CMAKE_SYSTEM_PROCESSOR=x86_64  ;;
        esac

        CMAKE_TOOLCHAIN_FILE="$PACKAGE_WORKING_DIR/android.toolchain.cmake"

        cat > "$CMAKE_TOOLCHAIN_FILE" <<EOF
message(STATUS "CMake command: \${CMAKE_COMMAND}")
message(STATUS "CMake version: \${CMAKE_VERSION}")

if ("\${BUILD_SHARED_LIBS}" STREQUAL "")
    set(BUILD_SHARED_LIBS Release)
endif()

set(ANDROID_ABI "${TARGET_PLATFORM_ABI}")
set(ANDROID_PLATFORM "android-${TARGET_PLATFORM_VERS}")
set(ANDROID_TOOLCHAIN clang)
set(ANDROID_ARM_NEON TRUE)
set(ANDROID_STL c++_shared)
include(${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake)

message(STATUS "CMAKE_HOST_SYSTEM_NAME: \${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "     CMAKE_SYSTEM_NAME: \${CMAKE_SYSTEM_NAME}")

set(CMAKE_BUILD_TYPE  $CMAKE_BUILD_TYPE)

set(CMAKE_C_COMPILER "$CC")
set(CMAKE_C_FLAGS "$CPPFLAGS $CFLAGS")

set(CMAKE_CXX_COMPILER "$CXX")
set(CMAKE_CXX_FLAGS "$CPPFLAGS $CXXFLAGS")

set(CMAKE_ASM_COMPILER "$CC")

set(CMAKE_SHARED_LINKER_FLAGS "$(printf '%s\n' "$LDFLAGS" | sed -e 's|--static||g' -e 's|-static||g')")
set(CMAKE_EXE_LINKER_FLAGS    "$LDFLAGS")

set(CMAKE_C_COMPILER_AR     "$AR")
set(CMAKE_C_COMPILER_RANLIB "$RANLIB")

set(CMAKE_CXX_COMPILER_AR     "$AR")
set(CMAKE_CXX_COMPILER_RANLIB "$RANLIB")

set(CMAKE_AR      "$AR")
set(CMAKE_RANLIB  "$RANLIB")

set(CMAKE_LINKER  "$LD")

set(CMAKE_NM      "$NM")
set(CMAKE_READELF "$READELF")

set(CMAKE_OBJCOPY "$OBJCOPY")
set(CMAKE_OBJDUMP "$OBJDUMP")

set(CMAKE_STRIP   "$STRIP")

set(CMAKE_ADDR2LINE "$ADDR2LINE")

if ("\${CMAKE_EXE_LINKER_FLAGS}" MATCHES ".*-static.*")
    set(CMAKE_SKIP_INSTALL_RPATH ON)
endif()

set(CMAKE_FIND_DEBUG_MODE $CMAKE_FIND_DEBUG_MODE)
set(CMAKE_FIND_ROOT_PATH "$CMAKE_FIND_ROOT_PATH")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

set(CMAKE_INSTALL_MESSAGE "$CMAKE_INSTALL_MESSAGE")
EOF

        NASM="$(command -v nasm || command -v yasm || true)"

        if [ -n "$NASM" ] ; then
            cat >> "$CMAKE_TOOLCHAIN_FILE" <<EOF
set(CMAKE_ASM_NASM_COMPILER "$NASM")
EOF
        fi

        if [ "$ENABLE_CCACHE" = 1 ] ; then
            cat >> "$CMAKE_TOOLCHAIN_FILE" <<EOF
set(NDK_CCACHE "$CCACHE")
EOF
        fi

        if [ "$VERBOSE_CMAKE" = 1 ] ; then
            bat --language=cmake --paging=never "$CMAKE_TOOLCHAIN_FILE"
        fi

        if [   -f "$PACKAGE_BCACHED_DIR/CMakeCache.txt" ] ; then
            rm -f "$PACKAGE_BCACHED_DIR/CMakeCache.txt"
        fi

        CMAKE_CONFIG_OPTIONS="-Wno-dev -DBUILD_TESTING=OFF -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_PREFIX='$PACKAGE_INSTALL_DIR' -DCMAKE_TOOLCHAIN_FILE='$CMAKE_TOOLCHAIN_FILE' -DCMAKE_VERBOSE_MAKEFILE='$CMAKE_VERBOSE_MAKEFILE' -DCMAKE_COLOR_MAKEFILE='$CMAKE_COLOR_MAKEFILE'"

        if [ -n "$CMAKE_PROJECT_INCLUDE" ] && [ -f "$CMAKE_PROJECT_INCLUDE" ] ; then
            CMAKE_CONFIG_OPTIONS="$CMAKE_CONFIG_OPTIONS -DCMAKE_PROJECT_INCLUDE=$CMAKE_PROJECT_INCLUDE"
        fi

        run "$CMAKE" "$CMAKE_CONFIG_OPTIONS" -S "$PACKAGE_BSCRIPT_DIR" -B "$PACKAGE_BCACHED_DIR" "$@"

        if [ -z "$CMAKE_BUILD_TARGETS" ] ; then
            run "$CMAKE" --build   "$PACKAGE_BCACHED_DIR"
        else
            run "$CMAKE" --build   "$PACKAGE_BCACHED_DIR" --target "$CMAKE_BUILD_TARGETS"
        fi

        if [ -z "$CMAKE_INSTALL_COMPONENTS" ] ; then
            run "$CMAKE" --install "$PACKAGE_BCACHED_DIR"
        else
            for component in $CMAKE_INSTALL_COMPONENTS
            do
            run "$CMAKE" --install "$PACKAGE_BCACHED_DIR" --component "$component"
            done
        fi
    fi
}

# https://github.com/xmake-io/xmake/issues/2003
# run in a subshell
xmakew() {
    XMAKE_CONFIG_OPTIONS="$@"

    XMAKE_CONFIG_OPTION_CLEAN=
    XMAKE_CONFIG_OPTION_MODE=
    XMAKE_CONFIG_OPTION_vD=

    for arg in $@
    do
        case $arg in
            -c|--clean)  XMAKE_CONFIG_OPTION_CLEAN=set ;;
            -m|--mode=*) XMAKE_CONFIG_OPTION_MODE=set  ;;
            -vD)         XMAKE_CONFIG_OPTION_vD=set ;;
        esac
    done

    if [ "$DEBUG_XMAKE" = 1 ] && [ -z "$XMAKE_CONFIG_OPTION_vD" ] ; then
        XMAKE_CONFIG_OPTIONS="$XMAKE_CONFIG_OPTION_vD -vD"
    fi

    if [ -z "$XMAKE_CONFIG_OPTION_CLEAN" ] ; then
        XMAKE_CONFIG_OPTIONS="$XMAKE_CONFIG_OPTIONS --clean"
    fi

    if [ -z "$XMAKE_CONFIG_OPTION_MODE" ] ; then
        XMAKE_CONFIG_OPTIONS="$XMAKE_CONFIG_OPTIONS --mode=$PROFILE"
    fi

    if [ "$BUILD_FOR_NATIVE" = 1 ] ; then
        run $XMAKE config $XMAKE_CONFIG_OPTIONS --project=$PACKAGE_BSCRIPT_DIR --buildir=$PACKAGE_BCACHED_DIR &&
        run $XMAKE --jobs=$BUILD_NJOBS &&
        run $XMAKE install -o "$PACKAGE_INSTALL_DIR"
    else
        XMAKE_CONFIG_OPTIONS="$XMAKE_CONFIG_OPTIONS --plat=android --arch=$TARGET_PLATFORM_ABI --ndk_sdkver=$TARGET_PLATFORM_VERS --toolchain=ndk --ndk=$ANDROID_NDK_HOME --buildir=$PACKAGE_BCACHED_DIR --cc=$CC --cxx=$CXX --cflags='$CFLAGS' --cxxflags='$CXXFLAGS' --ldflags='$LDFLAGS' --shflags='$LDFLAGS'"

        run $XMAKE config $XMAKE_CONFIG_OPTIONS &&
        run $XMAKE --jobs=$BUILD_NJOBS &&
        run $XMAKE install -o "$PACKAGE_INSTALL_DIR"
    fi
}

# https://mesonbuild.com/Cross-compilation.html
# run in a subshell
mesonw() {
    case $TARGET_PLATFORM_ARCH in
        armv7a)
            HOST_MACHINE_CPU_FAMILY='arm'
            HOST_MACHINE_CPU_NAME="$TARGET_PLATFORM_ARCH"
            ;;
        aarch64)
            HOST_MACHINE_CPU_FAMILY='aarch64'
            HOST_MACHINE_CPU_NAME='armv8a'
            ;;
        i686)
            HOST_MACHINE_CPU_FAMILY='x86'
            HOST_MACHINE_CPU_NAME="$TARGET_PLATFORM_ARCH"
            ;;
        x86_64)
            HOST_MACHINE_CPU_FAMILY='x86_64'
            HOST_MACHINE_CPU_NAME="$TARGET_PLATFORM_ARCH"
            ;;
    esac

    MESON_CROSS_FILE="$PACKAGE_BCACHED_DIR/cross-file"

    cat > "$MESON_CROSS_FILE" <<EOF
[host_machine]
system = 'android'
endian = 'little'
cpu_family = '$HOST_MACHINE_CPU_FAMILY'
cpu = '$HOST_MACHINE_CPU_NAME'

[binaries]
c = '$CC'
cpp = '$CXX'
ar = '$AR'
strip = '$STRIP'
cmake = '$CMAKE'
pkg-config = '$PKG_CONFIG'

[built-in options]
c_args = $(to_meson_array $CFLAGS $CPPFLAGS)
c_link_args = $(to_meson_array $LDFLAGS)
cpp_args = $(to_meson_array $CXXFLAGS $CPPFLAGS)
cpp_link_args = $(to_meson_array $LDFLAGS)
EOF

    MESON_SETUP_ARGS="--prefix=$PACKAGE_INSTALL_DIR --buildtype=$PROFILE --backend=ninja --pkg-config-path=$PKG_CONFIG_PATH --build.pkg-config-path=$PKG_CONFIG_PATH_FOR_BUILD --cross-file=$MESON_CROSS_FILE -Dlibdir=lib"

    if [ "$PACKAGE_PKGTYPE" = exe ] || [ "$PACKAGE_PKGTYPE" = pie ] ; then
        MESON_SETUP_ARGS="$MESON_SETUP_ARGS -Ddefault_library=static --prefer-static"
    else
        MESON_SETUP_ARGS="$MESON_SETUP_ARGS -Ddefault_library=both"
    fi

    MESON_COMPILE_ARGS="-C $PACKAGE_BCACHED_DIR -j $BUILD_NJOBS"
    MESON_INSTALL_ARGS="-C $PACKAGE_BCACHED_DIR"

    if [ "$VERBOSE_MESON" = 1 ] ; then
        MESON_COMPILE_ARGS="$MESON_COMPILE_ARGS -v"
    fi

    run "$MESON" setup   "$MESON_SETUP_ARGS" "$@" "$PACKAGE_BCACHED_DIR" "$PACKAGE_BSCRIPT_DIR" &&
    run "$MESON" compile "$MESON_COMPILE_ARGS" &&
    run "$MESON" install "$MESON_INSTALL_ARGS"
}

to_meson_array() {
    RESULT=

    for item in "$@"
    do
        if [ -z "$RESULT" ] ; then
            RESULT="'$item'"
        else
            RESULT="$RESULT, '$item'"
        fi
    done

    printf '[%s]\n' "$RESULT"
}

# https://developer.android.com/ndk/guides/ndk-build
ndk_build() {
    # https://developer.android.com/ndk/downloads/revision_history#expandable-33
    # Android NDK r7 (November 2011)
    if [ "$ENABLE_CCACHE" = 1 ] ; then
        export NDK_CCACHE=$CCACHE
    fi

    NDK_BUILD_ARGS="NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_PLATFORM=android-$TARGET_PLATFORM_VERS APP_STRIP_MODE=-S"

    case $PROFILE in
        debug)   NDK_BUILD_ARGS="$NDK_BUILD_ARGS NDK_DEBUG=1" ;;
        release) NDK_BUILD_ARGS="$NDK_BUILD_ARGS NDK_DEBUG=0" ;;
    esac

    if [ "$REQUEST_TO_EXPORT_COMPILE_COMMANDS_JSON" = 1 ] ; then
        NDK_BUILD_ARGS="$NDK_BUILD_ARGS GEN_COMPILE_COMMANDS_DB=true"
    fi

    if [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERBOSE" ] ; then
        NDK_BUILD_ARGS="$NDK_BUILD_ARGS V=1"
    fi

    if [ "$LOG_LEVEL" -ge "$LOG_LEVEL_VERY_VERBOSE" ] ; then
        NDK_BUILD_ARGS="$NDK_BUILD_ARGS NDK_LOG=1"
    fi

    run ndk-build $NDK_BUILD_ARGS
}

########################################################################

inspect_android_ndk_info() {
    [ -z "$1" ] && abort 1 "$NDKPKG_ARG0 ndkinfo <ANDROID-NDK-HOME> , <ANDROID-NDK-HOME> is not given."
    [ -d "$1" ] || abort 1 "'$1' was expected to be a directory, but it was not."

    NDK_SOURCE_PROPERTIES_FILEPATH="$1/source.properties"

    [ -e "$NDK_SOURCE_PROPERTIES_FILEPATH" ] || abort 1 "'$NDK_SOURCE_PROPERTIES_FILEPATH' was expected to be exist, but it was not."
    [ -f "$NDK_SOURCE_PROPERTIES_FILEPATH" ] || abort 1 "'$NDK_SOURCE_PROPERTIES_FILEPATH' was expected to be a regular file, but it was not."

    ANDROID_CMAKE_TOOLCHAIN_FILE="$1/build/cmake/android.toolchain.cmake"

    [ -e "$ANDROID_CMAKE_TOOLCHAIN_FILE" ] || abort 1 "'$ANDROID_CMAKE_TOOLCHAIN_FILE' was expected to be exist, but it was not."
    [ -f "$ANDROID_CMAKE_TOOLCHAIN_FILE" ] || abort 1 "'$ANDROID_CMAKE_TOOLCHAIN_FILE' was expected to be a regular file, but it was not."

    ANDROID_NDK_VERSION=
    ANDROID_NDK_VERSION_MAJOR=

    ANDROID_NDK_VERSION="$(sed -n '/Pkg.Revision/p' "$NDK_SOURCE_PROPERTIES_FILEPATH" | sed  's/Pkg\.Revision = \(.*\).*/\1/')"

    if [ -z "$ANDROID_NDK_VERSION" ] ; then
        abort 1 "no Pkg.Revision property in $NDK_SOURCE_PROPERTIES_FILEPATH"
    fi

    ANDROID_NDK_VERSION_MAJOR="$(printf '%s\n' "$ANDROID_NDK_VERSION" | cut -d. -f1)"

    if [ "$NATIVE_PLATFORM_KIND" = darwin ] ; then
        ANDROID_NDK_TOOLCHAIN_HOST_TAG='darwin-x86_64'
    else
        ANDROID_NDK_TOOLCHAIN_HOST_TAG="linux-$NATIVE_PLATFORM_ARCH"
    fi

    ANDROID_NDK_TOOLCHAIN_ROOT="$1/toolchains/llvm/prebuilt/$ANDROID_NDK_TOOLCHAIN_HOST_TAG"

    [ -e "$ANDROID_NDK_TOOLCHAIN_ROOT" ] || abort 1 "'$ANDROID_NDK_TOOLCHAIN_ROOT' was expected to be exist, but it was not."
    [ -d "$ANDROID_NDK_TOOLCHAIN_ROOT" ] || abort 1 "'$ANDROID_NDK_TOOLCHAIN_ROOT' was expected to be a directory, but it was not."

    ANDROID_NDK_TOOLCHAIN_BIND="$ANDROID_NDK_TOOLCHAIN_ROOT/bin"

    [ -e "$ANDROID_NDK_TOOLCHAIN_BIND" ] || abort 1 "'$ANDROID_NDK_TOOLCHAIN_BIND' was expected to be exist, but it was not."
    [ -d "$ANDROID_NDK_TOOLCHAIN_BIND" ] || abort 1 "'$ANDROID_NDK_TOOLCHAIN_BIND' was expected to be a directory, but it was not."

    ANDROID_NDK_SYSROOT="$ANDROID_NDK_TOOLCHAIN_ROOT/sysroot"

    [ -e "$ANDROID_NDK_SYSROOT" ] || abort 1 "'$ANDROID_NDK_SYSROOT' was expected to be exist, but it was not."
    [ -d "$ANDROID_NDK_SYSROOT" ] || abort 1 "'$ANDROID_NDK_SYSROOT' was expected to be a directory, but it was not."

    #########################################################################################

    ANDROID_NDK_CC="$ANDROID_NDK_TOOLCHAIN_BIND/clang"
    ANDROID_NDK_CXX="$ANDROID_NDK_TOOLCHAIN_BIND/clang++"
    ANDROID_NDK_CPP="$ANDROID_NDK_CC -E"

    # https://github.com/android/ndk/wiki/Changelog-r22
    # https://github.com/android/ndk/wiki/Changelog-r23
    if [ "$ANDROID_NDK_VERSION_MAJOR" -ge 22 ] ; then
        ANDROID_NDK_LD="$ANDROID_NDK_TOOLCHAIN_BIND/ld.lld"
        ANDROID_NDK_AS="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-as"
        ANDROID_NDK_AR="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-ar"
        ANDROID_NDK_NM="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-nm"
        ANDROID_NDK_SIZE="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-size"
        ANDROID_NDK_STRIP="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-strip"
        ANDROID_NDK_RANLIB="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-ranlib"
        ANDROID_NDK_STRINGS="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-strings"
        ANDROID_NDK_OBJDUMP="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-objdump"
        ANDROID_NDK_OBJCOPY="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-objcopy"
        ANDROID_NDK_READELF="$ANDROID_NDK_TOOLCHAIN_BIND/llvm-readelf"
    else
        ANDROID_NDK_LD="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-ld"
        ANDROID_NDK_AS="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-as"
        ANDROID_NDK_AR="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-ar"
        ANDROID_NDK_NM="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-nm"
        ANDROID_NDK_SIZE="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-size"
        ANDROID_NDK_STRIP="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-strip"
        ANDROID_NDK_RANLIB="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-ranlib"
        ANDROID_NDK_STRINGS="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-strings"
        ANDROID_NDK_OBJDUMP="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-objdump"
        ANDROID_NDK_OBJCOPY="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-objcopy"
        ANDROID_NDK_READELF="$ANDROID_NDK_TOOLCHAIN_BIND/aarch64-linux-android-readelf"
    fi

    #########################################################################################

    ANDROID_NDK_SUPPORTED_SDK_API_LEVEL_ALL="$(ls "$ANDROID_NDK_TOOLCHAIN_BIND" | sed -n '/aarch64-linux-android[1-9][0-9]-clang++/p' | cut -d- -f3 | sed 's/android//')"
    ANDROID_NDK_SUPPORTED_MIN_SDK_API_LEVEL="$(printf '%s\n' "$ANDROID_NDK_SUPPORTED_SDK_API_LEVEL_ALL" | sort | head -n 1)"
    ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL="$(printf '%s\n' "$ANDROID_NDK_SUPPORTED_SDK_API_LEVEL_ALL" | sort | tail -n 1)"

    #########################################################################################

    ANDROID_NDK_HOME="$1"
    ANDROID_NDK_ROOT="$1"
}

println_android_ndk_info() {
    cat <<EOF
ANDROID_NDK_HOME='$ANDROID_NDK_HOME'
ANDROID_NDK_ROOT='$ANDROID_NDK_ROOT'
ANDROID_NDK_VERSION='$ANDROID_NDK_VERSION'
ANDROID_NDK_VERSION_MAJOR='$ANDROID_NDK_VERSION_MAJOR'
ANDROID_NDK_TOOLCHAIN_ROOT='$ANDROID_NDK_TOOLCHAIN_ROOT'
ANDROID_NDK_TOOLCHAIN_BIND='$ANDROID_NDK_TOOLCHAIN_BIND'
ANDROID_NDK_SYSROOT='$ANDROID_NDK_SYSROOT'
ANDROID_NDK_CC='$ANDROID_NDK_CC'
ANDROID_NDK_CXX='$ANDROID_NDK_CXX'
ANDROID_NDK_CPP='$ANDROID_NDK_CPP'
ANDROID_NDK_LD='$ANDROID_NDK_LD'
ANDROID_NDK_AS='$ANDROID_NDK_AS'
ANDROID_NDK_AR='$ANDROID_NDK_AR'
ANDROID_NDK_NM='$ANDROID_NDK_NM'
ANDROID_NDK_SIZE='$ANDROID_NDK_SIZE'
ANDROID_NDK_STRIP='$ANDROID_NDK_STRIP'
ANDROID_NDK_RANLIB='$ANDROID_NDK_RANLIB'
ANDROID_NDK_STRINGS='$ANDROID_NDK_STRINGS'
ANDROID_NDK_OBJDUMP='$ANDROID_NDK_OBJDUMP'
ANDROID_NDK_OBJCOPY='$ANDROID_NDK_OBJCOPY'
ANDROID_NDK_READELF='$ANDROID_NDK_READELF'
ANDROID_NDK_SUPPORTED_MIN_SDK_API_LEVEL='$ANDROID_NDK_SUPPORTED_MIN_SDK_API_LEVEL'
ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL='$ANDROID_NDK_SUPPORTED_MAX_SDK_API_LEVEL'
EOF
}

# setup_android_ndk_env [ANDROID_NDK_HOME]
  setup_android_ndk_env() {
    if [ -z "$1" ] ; then
        if [ "$NATIVE_PLATFORM_KIND" = android ] ; then
            # use comunity compiled Android NDK for aarch64-linux right now, I might compile my own at some point.
            # https://github.com/lzhiyong/termux-ndk/releases/tag/android-ndk
            ANDROID_NDK_REVISION='r26b'
        else
            ANDROID_NDK_REVISION='r26d'
        fi

        ANDROID_NDK_PKG="android-ndk-$ANDROID_NDK_REVISION"

        ANDROID_NDK_HOME="$UPPM_HOME/installed/$ANDROID_NDK_PKG"

        if ! uppm is-installed "$ANDROID_NDK_PKG" ; then
            note "Due to --ndk-home=<ANDROID-NDK-HOME> option is unspecified, Android NDK ($ANDROID_NDK_REVISION) will be installed via uppm."

            uppm about
            uppm update
            uppm install "$ANDROID_NDK_PKG"

            case $NATIVE_PLATFORM_KIND in
                linux)
                    # https://github.com/microsoft/WSL/issues/8681
                    # https://github.com/microsoft/WSL/issues/4071
                    if grep -q -i Microsoft /proc/version ; then
                        patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 "$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/clang-17"
                    fi
                    ;;
                darwin)
                    # https://github.com/android/ndk/issues/1549
                    # remove the yasm shipped with Android NDK and use our own
                    rm -rf "$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/yasm"
                    ;;
            esac
        fi
    else
        ANDROID_NDK_HOME="$1"
    fi

    inspect_android_ndk_info "$ANDROID_NDK_HOME"

    if [ "$DUMP_NDK" = 1 ] ; then
        println_android_ndk_info
    fi

    export ANDROID_NDK_HOME
    export ANDROID_NDK_ROOT
}
